familiarity 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +67 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/familiarity/application.js +16 -0
- data/app/assets/javascripts/familiarity/familiarity.js.erb +193 -0
- data/app/assets/javascripts/familiarity/familiarity_admin.js.erb +150 -0
- data/app/assets/javascripts/familiarity/jquery.cookie.js +117 -0
- data/app/assets/javascripts/familiarity/jquery.tooltipster.js +1282 -0
- data/app/assets/stylesheets/familiarity/application.css +17 -0
- data/app/assets/stylesheets/familiarity/familiarities.css +4 -0
- data/app/assets/stylesheets/familiarity/familiarity.css.scss +121 -0
- data/app/assets/stylesheets/familiarity/themes/tooltipster-light.css +12 -0
- data/app/assets/stylesheets/familiarity/themes/tooltipster-noir.css +12 -0
- data/app/assets/stylesheets/familiarity/themes/tooltipster-punk.css +12 -0
- data/app/assets/stylesheets/familiarity/themes/tooltipster-shadow.css +12 -0
- data/app/assets/stylesheets/familiarity/tooltipster.css +274 -0
- data/app/controllers/familiarity/application_controller.rb +4 -0
- data/app/controllers/familiarity/familiarities_controller.rb +22 -0
- data/app/helpers/familiarity/application_helper.rb +32 -0
- data/app/helpers/familiarity/familiarities_helper.rb +4 -0
- data/app/views/familiarity/familiarities/index.json.erb +1 -0
- data/app/views/layouts/familiarity/application.html.erb +14 -0
- data/config/routes.rb +7 -0
- data/lib/familiarity/engine.rb +17 -0
- data/lib/familiarity/version.rb +3 -0
- data/lib/familiarity.rb +4 -0
- data/lib/tasks/familiarity_tasks.rake +4 -0
- data/test/controllers/familiarity/familiarities_controller_test.rb +9 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +78 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/familiarity_test.rb +7 -0
- data/test/helpers/familiarity/familiarities_helper_test.rb +6 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2dd519d51c98acb014642d12b06e4de9a6f82a1b
|
4
|
+
data.tar.gz: 0584a4efa27e079b51ab5e2e1dddd7b7187f872f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 404901d952f72cb7af44f93413df82792c1c00226e3560bf4553514994f14c1f02f5f8d0d4006f6f14d7fe8b12c2a3c4ad1944a63983f1e4a1835d08630c99f3
|
7
|
+
data.tar.gz: 55ac357617105be747e9e0f4e708bfdc4bf24136b89360ff0d4ed8ab260aee3e43c82a96fe1364deba99415c9cd723d079e7bd597cbc3ef52fb9a03ec1c42b7f
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
= \Familiarity
|
2
|
+
|
3
|
+
This gem packages a rails engine which provides an interactive demo of features/entities on any given page.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'familiarity', :git => 'git@github.com:praveenkumarsinha/familiarity.git'
|
10
|
+
|
11
|
+
Then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Mount Familiarity at specific location (from routes.rb of application):
|
16
|
+
|
17
|
+
mount Familiarity::Engine, at: "/some_specific_location"
|
18
|
+
|
19
|
+
Add javascript(s) in application manifest (most probably from app/assets/javascripts/application.js):
|
20
|
+
|
21
|
+
//= require familiarity/application
|
22
|
+
|
23
|
+
Add stylesheet(s) in application manifest (most probably from app/assets/stylesheets/application.css):
|
24
|
+
|
25
|
+
*= require familiarity/application
|
26
|
+
|
27
|
+
Add familiarity's switch-board on all the pages (append following helper at the end as body content in layout):
|
28
|
+
|
29
|
+
<%= familiaritySwitchBoard %>
|
30
|
+
|
31
|
+
Add familiarity's view on all the pages (append following helper at the end as body content in layout):
|
32
|
+
|
33
|
+
<%= familiarityView %>
|
34
|
+
|
35
|
+
== Helpers
|
36
|
+
|
37
|
+
To provide a switch board where an user (or may be a bunch of users in any specific environment of application) want to add/edit/update or delete annotations on any page .
|
38
|
+
|
39
|
+
<%= familiaritySwitchBoard %>
|
40
|
+
|
41
|
+
|
42
|
+
To provide annotations view of elements, one element at a time on the first visit of page.
|
43
|
+
|
44
|
+
<%= familiarityView %>
|
45
|
+
<%= familiarityView({
|
46
|
+
escape_to_exit: true, #Exits on ESC key press.
|
47
|
+
f1_to_start: true, #Starts on F1 key press.
|
48
|
+
show_tips_recursively: false, #To restart annotations display after complete traverse of available annotations.
|
49
|
+
mandatory_all_tips: true, #To show all tips(annotations) at least once (before enabling ESC key for exit).
|
50
|
+
traverse_back: true, #By default 'LEFT' arrow key is available to visit back but which can be disabled with a 'false' here.
|
51
|
+
remember_duration: 30 #Duration(in days) in which application need to show familiarity view irrespective whether user has viewed them or not.
|
52
|
+
}) %>
|
53
|
+
|
54
|
+
|
55
|
+
== Dependencies used
|
56
|
+
|
57
|
+
1. https://github.com/carhartl/jquery-cookie
|
58
|
+
2. http://iamceege.github.io/tooltipster/
|
59
|
+
|
60
|
+
|
61
|
+
== Contributing
|
62
|
+
|
63
|
+
1. Fork it ( https://github.com/praveenkumarsinha/familiarity/fork )
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Familiarity'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1,16 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require ../familiarity/jquery.cookie
|
14
|
+
//= require ../familiarity/jquery.tooltipster
|
15
|
+
//= require_tree .
|
16
|
+
|
@@ -0,0 +1,193 @@
|
|
1
|
+
var Familiarity = function (options) {
|
2
|
+
this.escape_to_exit = options.escape_to_exit;
|
3
|
+
this.f1_to_start = options.f1_to_start;
|
4
|
+
this.show_tips_recursively = options.show_tips_recursively;
|
5
|
+
this.mandatory_all_tips = options.mandatory_all_tips;
|
6
|
+
this.traverse_back = options.traverse_back;
|
7
|
+
|
8
|
+
this.familiaritiesUrl = '<%= Familiarity::Engine.routes.url_helpers.familiarities_path(format: :json) %>';
|
9
|
+
// To retain the flag even after reset() method familiarityAllTipsVisited flag is defined here.
|
10
|
+
this.familiarityAllTipsVisited = false;
|
11
|
+
this.reset();
|
12
|
+
Familiarity.setCurrentObject(this);
|
13
|
+
}
|
14
|
+
Familiarity.setCurrentObject = function (current_object) {
|
15
|
+
return (this.currentObject = current_object);
|
16
|
+
}
|
17
|
+
Familiarity.getCurrentObject = function () {
|
18
|
+
return this.currentObject
|
19
|
+
}
|
20
|
+
Familiarity.prototype = {
|
21
|
+
reset: function () {
|
22
|
+
// this.familiarityAllTipsVisited = false;
|
23
|
+
this.familiarityRenderedFlag = false;
|
24
|
+
this.familiarity_hash_pointer = -1;
|
25
|
+
this.familiarity_hash = {};
|
26
|
+
this.familiarity_bubbles = [];
|
27
|
+
},
|
28
|
+
familiarity_hash_keys: function () {
|
29
|
+
return ($.map(this.familiarity_hash, function (v, k) {
|
30
|
+
return k;
|
31
|
+
}));
|
32
|
+
},
|
33
|
+
showNextBubble: function () {
|
34
|
+
if (this.familiarity_hash_keys().length <= 0) {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
this.familiarity_hash_pointer++;
|
38
|
+
if ((this.familiarity_hash_pointer + 1) > this.familiarity_hash_keys().length) {
|
39
|
+
this.familiarityAllTipsVisited = true
|
40
|
+
if (this.show_tips_recursively) {
|
41
|
+
this.familiarity_hash_pointer = 0;
|
42
|
+
} else {
|
43
|
+
this.familiarityView(false);
|
44
|
+
return true;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
this.showOneByOne();
|
48
|
+
},
|
49
|
+
showPreviousBubble: function () {
|
50
|
+
if (this.familiarity_hash_keys().length <= 0) {
|
51
|
+
return false;
|
52
|
+
}
|
53
|
+
if (!this.traverse_back) {
|
54
|
+
return false;
|
55
|
+
}
|
56
|
+
this.familiarity_hash_pointer--;
|
57
|
+
if (this.familiarity_hash_pointer < 0) {
|
58
|
+
if (this.show_tips_recursively) {
|
59
|
+
this.familiarity_hash_pointer = this.familiarity_hash_keys().length - 1;
|
60
|
+
} else {
|
61
|
+
this.familiarity_hash_pointer = 0;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
this.showOneByOne();
|
65
|
+
},
|
66
|
+
showOneByOne: function () {
|
67
|
+
// console.log(this.familiarity_hash_pointer);
|
68
|
+
// console.log(this.familiarity_hash);
|
69
|
+
// console.log(this.familiarity_bubbles);
|
70
|
+
this.hideFBubbles();
|
71
|
+
return this.showFBubble();
|
72
|
+
},
|
73
|
+
showFBubble: function () {
|
74
|
+
var current_bubble_key = this.familiarity_hash_keys()[this.familiarity_hash_pointer];
|
75
|
+
var element = $(current_bubble_key)
|
76
|
+
var content = this.familiarity_hash[current_bubble_key];
|
77
|
+
|
78
|
+
if (element.length <= 0) {
|
79
|
+
return false;
|
80
|
+
}
|
81
|
+
|
82
|
+
element.addClass('familiarity-bubble-parent')
|
83
|
+
.tooltipster({
|
84
|
+
content: $('<span><strong>' + content.replace(/\n/g, "<br/>") + '</strong></span>'),
|
85
|
+
maxWidth: 400,
|
86
|
+
animation: 'grow', //fade, grow, swing, slide, fall
|
87
|
+
autoClose: true, //true, false
|
88
|
+
position: 'bottom-right', //right, left, top, top-right, top-left, bottom, bottom-right, bottom-left
|
89
|
+
delay: 700,
|
90
|
+
speed: 700,
|
91
|
+
theme: 'tooltipster-default',
|
92
|
+
touchDevices: false,
|
93
|
+
trigger: 'custom' //hover, click, custom
|
94
|
+
});
|
95
|
+
element.tooltipster('show');
|
96
|
+
// console.log(element.css('background-color'));
|
97
|
+
// if (element.css('background-color') == 'transparent') {
|
98
|
+
// element.css('background-color', 'white')
|
99
|
+
// }
|
100
|
+
this.familiarity_bubbles.push(element)
|
101
|
+
return true;
|
102
|
+
},
|
103
|
+
hideFBubbles: function () {
|
104
|
+
while (this.familiarity_bubbles.length > 0) {
|
105
|
+
this.familiarity_bubbles.pop().tooltipster('destroy').removeClass('familiarity-bubble-parent').attr('title', null);
|
106
|
+
}
|
107
|
+
},
|
108
|
+
fetchFamiliarities: function (callback) {
|
109
|
+
if (typeof(callback) != 'function') {
|
110
|
+
callback = function (familiarity_hash) {
|
111
|
+
console.log('familiarity_hash');
|
112
|
+
console.log(familiarity_hash);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
var _this = this;
|
116
|
+
$.get(this.familiaritiesUrl, function (data) {
|
117
|
+
var familiarity_hash = data[$(location).attr('pathname')]
|
118
|
+
if (familiarity_hash == null) {
|
119
|
+
familiarity_hash = {}
|
120
|
+
}
|
121
|
+
_this.familiarity_hash = familiarity_hash;
|
122
|
+
callback(familiarity_hash);
|
123
|
+
});
|
124
|
+
},
|
125
|
+
familiarityView: function (enable) {
|
126
|
+
var _this = this;
|
127
|
+
if (typeof(enable) == 'undefined') {
|
128
|
+
enable = true;
|
129
|
+
}
|
130
|
+
if (enable == true) {
|
131
|
+
//Re-setting all values and variables (in case is there any half done state)
|
132
|
+
this.reset();
|
133
|
+
|
134
|
+
//Making bubble pop-out //////////////////
|
135
|
+
this.fetchFamiliarities(function (familiarity_hash) {
|
136
|
+
if (_this.familiarity_hash_keys().length > 0) {
|
137
|
+
//Rendering overlay
|
138
|
+
$('body').addClass('familiarity-view').append($('<div id="familiarity_dim"></div>'));
|
139
|
+
|
140
|
+
//Rendering first bubble (via Next Bubble)
|
141
|
+
_this.showNextBubble();
|
142
|
+
|
143
|
+
//Marking flag that familiarity_view is rendered
|
144
|
+
_this.familiarityRenderedFlag = true;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
);
|
148
|
+
|
149
|
+
} else {
|
150
|
+
|
151
|
+
// If option 'mandatory_all_tips' is true then make sure all tips has been rendered
|
152
|
+
// before exit of familiarity view
|
153
|
+
if (this.mandatory_all_tips && (!this.familiarityAllTipsVisited)) {
|
154
|
+
return false;
|
155
|
+
}
|
156
|
+
|
157
|
+
//Removing bubbles
|
158
|
+
_this.hideFBubbles();
|
159
|
+
|
160
|
+
//Removing rendered overlay
|
161
|
+
$('#familiarity_dim').remove();
|
162
|
+
$('body').removeClass('familiarity-view');
|
163
|
+
|
164
|
+
//Marking flag that familiarity_view is removed from viewport
|
165
|
+
this.familiarityRenderedFlag = false;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
}
|
170
|
+
|
171
|
+
$(document).on("page:change", function () {
|
172
|
+
// Show and hide on F1 and ESC key respectively
|
173
|
+
$('body').keyup(function (e) {
|
174
|
+
var _this = Familiarity.getCurrentObject();
|
175
|
+
if (typeof(_this) != "undefined" && e.keyCode == 27 && _this.escape_to_exit && _this.familiarityRenderedFlag) { //ESC key pressed
|
176
|
+
_this.familiarityView(false);
|
177
|
+
}
|
178
|
+
if (typeof(_this) != "undefined" && e.keyCode == 112 && _this.f1_to_start && !_this.familiarityRenderedFlag) { //F1 key pressed
|
179
|
+
_this.familiarityView(true);
|
180
|
+
}
|
181
|
+
if (typeof(_this) != "undefined" && e.keyCode == 37 && _this.familiarityRenderedFlag) { //LEFT arrow key pressed
|
182
|
+
_this.showPreviousBubble();
|
183
|
+
}
|
184
|
+
if (typeof(_this) != "undefined" && e.keyCode == 39 && _this.familiarityRenderedFlag) { //RIGHT arrow key pressed
|
185
|
+
_this.showNextBubble()
|
186
|
+
}
|
187
|
+
}).mousedown(function (e) {
|
188
|
+
var _this = Familiarity.getCurrentObject();
|
189
|
+
if (typeof(_this) != "undefined" && _this.familiarityRenderedFlag) { //Show next bubble on mouse down('click')
|
190
|
+
_this.showNextBubble()
|
191
|
+
}
|
192
|
+
});
|
193
|
+
});
|
@@ -0,0 +1,150 @@
|
|
1
|
+
jQuery.fn.getPath = function () {
|
2
|
+
if (this.length != 1) throw 'Requires one element.';
|
3
|
+
|
4
|
+
var path, node = this;
|
5
|
+
while (node.length) {
|
6
|
+
var realNode = node[0], name = realNode.localName;
|
7
|
+
if (!name) break;
|
8
|
+
name = name.toLowerCase();
|
9
|
+
|
10
|
+
var parent = node.parent();
|
11
|
+
|
12
|
+
var siblings = parent.children(name);
|
13
|
+
if (siblings.length > 1) {
|
14
|
+
name += ':eq(' + siblings.index(realNode) + ')';
|
15
|
+
}
|
16
|
+
|
17
|
+
path = name + (path ? '>' + path : '');
|
18
|
+
node = parent;
|
19
|
+
}
|
20
|
+
|
21
|
+
return path;
|
22
|
+
};
|
23
|
+
|
24
|
+
var FamiliarityAdmin = function () {
|
25
|
+
this.familiarityEditorialSet = {};
|
26
|
+
this.familiaritySaveUrl = '<%=Familiarity::Engine.routes.url_helpers.save_familiarities_path(format: :json)%>';
|
27
|
+
this.familiaritiesUrl = '<%= Familiarity::Engine.routes.url_helpers.familiarities_path(format: :json) %>';
|
28
|
+
}
|
29
|
+
|
30
|
+
FamiliarityAdmin.familiaritySwitchBoard = function () {
|
31
|
+
var familiarity_admin = new FamiliarityAdmin();
|
32
|
+
|
33
|
+
var switch_state = 'On';
|
34
|
+
$('div.familiaritySwitch').remove();
|
35
|
+
var _div = $('<div class="familiaritySwitch"></div>').html('<div class="text_content">Switch ' + switch_state + ' familiarity!</div>').click(function () {
|
36
|
+
familiarity_admin.familiaritySwitch(switch_state);
|
37
|
+
switch_state = (switch_state == "On") ? "Off" : "On";
|
38
|
+
$(this).html('<div class="text_content">Switch ' + switch_state + ' familiarity!</div>');
|
39
|
+
}).appendTo($('body'));
|
40
|
+
}
|
41
|
+
|
42
|
+
FamiliarityAdmin.prototype = {
|
43
|
+
findOrBuildPopup: function (selection_path, inner_text) {
|
44
|
+
if (typeof(inner_text) == 'undefined') {
|
45
|
+
inner_text = "";
|
46
|
+
}
|
47
|
+
var _div = this.familiarityEditorialSet[selection_path];
|
48
|
+
if (_div == null) {
|
49
|
+
var _div = $('<div class="familiarityPopUpEdit" style="z-index: 20;position: absolute;left: 0;top: 0;display: none"><textarea class="textarea_class" placeholder="Short sweet tutorial goes in here."></textarea><br/><a class="a_class">Close</a></div>');
|
50
|
+
|
51
|
+
//Adding 'Close' handler
|
52
|
+
_div.children('a').click(function () {
|
53
|
+
$(this).parents('div.familiarityPopUpEdit').hide();
|
54
|
+
});
|
55
|
+
|
56
|
+
//Populating textarea
|
57
|
+
_div.children('textarea').val(inner_text);
|
58
|
+
|
59
|
+
this.familiarityEditorialSet[selection_path] = _div;
|
60
|
+
|
61
|
+
_div.appendTo($('body'));
|
62
|
+
}
|
63
|
+
$.each(this.familiarityEditorialSet, function (k, v) {
|
64
|
+
v.hide();
|
65
|
+
});
|
66
|
+
return _div;
|
67
|
+
},
|
68
|
+
startFamiliarizing: function () {
|
69
|
+
var _current_object = this;
|
70
|
+
$('.familiarityTag').bind("mouseenter.myFamiliarity", function (e) {
|
71
|
+
var _this = $(this);
|
72
|
+
var currentSelectionPath = _this.getPath();
|
73
|
+
// console.log(currentSelectionPath);
|
74
|
+
_this.addClass('familiar-selector');
|
75
|
+
_this.parents().removeClass('familiar-selector');
|
76
|
+
|
77
|
+
e.stopImmediatePropagation();
|
78
|
+
}).bind("mouseleave.myFamiliarity", function (e) {
|
79
|
+
var _this = $(this);
|
80
|
+
var currentSelectionPath = _this.getPath();
|
81
|
+
_this.removeClass('familiar-selector');
|
82
|
+
|
83
|
+
e.stopImmediatePropagation();
|
84
|
+
}).bind("click.myFamiliarity", function (e) {
|
85
|
+
var _this = $(this);
|
86
|
+
var currentSelectionPath = _this.getPath();
|
87
|
+
|
88
|
+
var _left_position = _this.position().left;
|
89
|
+
var _top_position = _this.position().top + _this.height();
|
90
|
+
|
91
|
+
var _div = _current_object.findOrBuildPopup(currentSelectionPath).css({
|
92
|
+
left: _left_position,
|
93
|
+
top: _top_position
|
94
|
+
}).show().children('textarea').focus();
|
95
|
+
|
96
|
+
// console.log(_this);
|
97
|
+
e.preventDefault();
|
98
|
+
e.stopPropagation();
|
99
|
+
});
|
100
|
+
},
|
101
|
+
|
102
|
+
saveToBackEnd: function () {
|
103
|
+
var _result_hash = {}
|
104
|
+
$.each(this.familiarityEditorialSet, function (k, v) {
|
105
|
+
if (v.children('textarea').val().trim().length > 0) {
|
106
|
+
_result_hash[k] = v.children('textarea').val();
|
107
|
+
}
|
108
|
+
})
|
109
|
+
jQuery.post(this.familiaritySaveUrl, {
|
110
|
+
from_page: $(location).attr('pathname'),
|
111
|
+
'familiarity_hash': _result_hash
|
112
|
+
});
|
113
|
+
},
|
114
|
+
|
115
|
+
stopFamiliarizing: function () {
|
116
|
+
$('.familiarityTag').unbind('.myFamiliarity');
|
117
|
+
},
|
118
|
+
|
119
|
+
familiaritySwitch: function (i_switch) {
|
120
|
+
if (i_switch == "Off") {
|
121
|
+
this.stopFamiliarizing();
|
122
|
+
$('.familiarityPopUpEdit').hide();
|
123
|
+
if (confirm("Do you want to save the collected familiarity data?")) {
|
124
|
+
this.saveToBackEnd();
|
125
|
+
}
|
126
|
+
}
|
127
|
+
$.each($('body *:not(.familiaritySwitch, .familiarityPopUpEdit)'), function (i, e) {
|
128
|
+
if (i_switch == "On") {
|
129
|
+
if ($(e).parents('.familiarityPopUpEdit').length <= 0) {
|
130
|
+
$(e).addClass('familiarityTag');
|
131
|
+
}
|
132
|
+
} else {
|
133
|
+
$(e).removeClass('familiarityTag');
|
134
|
+
}
|
135
|
+
});
|
136
|
+
if (i_switch == "On") {
|
137
|
+
var _current_object = this;
|
138
|
+
this.startFamiliarizing();
|
139
|
+
$.get(this.familiaritiesUrl, function (data) {
|
140
|
+
var familiarity_hash = data[$(location).attr('pathname')]
|
141
|
+
if (familiarity_hash == null) {
|
142
|
+
familiarity_hash = {}
|
143
|
+
}
|
144
|
+
$.each(familiarity_hash, function (k, v) {
|
145
|
+
_current_object.findOrBuildPopup(k, v);
|
146
|
+
});
|
147
|
+
});
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
/*!
|
2
|
+
* jQuery Cookie Plugin v1.4.1
|
3
|
+
* https://github.com/carhartl/jquery-cookie
|
4
|
+
*
|
5
|
+
* Copyright 2013 Klaus Hartl
|
6
|
+
* Released under the MIT license
|
7
|
+
*/
|
8
|
+
(function (factory) {
|
9
|
+
if (typeof define === 'function' && define.amd) {
|
10
|
+
// AMD
|
11
|
+
define(['jquery'], factory);
|
12
|
+
} else if (typeof exports === 'object') {
|
13
|
+
// CommonJS
|
14
|
+
factory(require('jquery'));
|
15
|
+
} else {
|
16
|
+
// Browser globals
|
17
|
+
factory(jQuery);
|
18
|
+
}
|
19
|
+
}(function ($) {
|
20
|
+
|
21
|
+
var pluses = /\+/g;
|
22
|
+
|
23
|
+
function encode(s) {
|
24
|
+
return config.raw ? s : encodeURIComponent(s);
|
25
|
+
}
|
26
|
+
|
27
|
+
function decode(s) {
|
28
|
+
return config.raw ? s : decodeURIComponent(s);
|
29
|
+
}
|
30
|
+
|
31
|
+
function stringifyCookieValue(value) {
|
32
|
+
return encode(config.json ? JSON.stringify(value) : String(value));
|
33
|
+
}
|
34
|
+
|
35
|
+
function parseCookieValue(s) {
|
36
|
+
if (s.indexOf('"') === 0) {
|
37
|
+
// This is a quoted cookie as according to RFC2068, unescape...
|
38
|
+
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
39
|
+
}
|
40
|
+
|
41
|
+
try {
|
42
|
+
// Replace server-side written pluses with spaces.
|
43
|
+
// If we can't decode the cookie, ignore it, it's unusable.
|
44
|
+
// If we can't parse the cookie, ignore it, it's unusable.
|
45
|
+
s = decodeURIComponent(s.replace(pluses, ' '));
|
46
|
+
return config.json ? JSON.parse(s) : s;
|
47
|
+
} catch(e) {}
|
48
|
+
}
|
49
|
+
|
50
|
+
function read(s, converter) {
|
51
|
+
var value = config.raw ? s : parseCookieValue(s);
|
52
|
+
return $.isFunction(converter) ? converter(value) : value;
|
53
|
+
}
|
54
|
+
|
55
|
+
var config = $.cookie = function (key, value, options) {
|
56
|
+
|
57
|
+
// Write
|
58
|
+
|
59
|
+
if (value !== undefined && !$.isFunction(value)) {
|
60
|
+
options = $.extend({}, config.defaults, options);
|
61
|
+
|
62
|
+
if (typeof options.expires === 'number') {
|
63
|
+
var days = options.expires, t = options.expires = new Date();
|
64
|
+
t.setTime(+t + days * 864e+5);
|
65
|
+
}
|
66
|
+
|
67
|
+
return (document.cookie = [
|
68
|
+
encode(key), '=', stringifyCookieValue(value),
|
69
|
+
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
70
|
+
options.path ? '; path=' + options.path : '',
|
71
|
+
options.domain ? '; domain=' + options.domain : '',
|
72
|
+
options.secure ? '; secure' : ''
|
73
|
+
].join(''));
|
74
|
+
}
|
75
|
+
|
76
|
+
// Read
|
77
|
+
|
78
|
+
var result = key ? undefined : {};
|
79
|
+
|
80
|
+
// To prevent the for loop in the first place assign an empty array
|
81
|
+
// in case there are no cookies at all. Also prevents odd result when
|
82
|
+
// calling $.cookie().
|
83
|
+
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
84
|
+
|
85
|
+
for (var i = 0, l = cookies.length; i < l; i++) {
|
86
|
+
var parts = cookies[i].split('=');
|
87
|
+
var name = decode(parts.shift());
|
88
|
+
var cookie = parts.join('=');
|
89
|
+
|
90
|
+
if (key && key === name) {
|
91
|
+
// If second argument (value) is a function it's a converter...
|
92
|
+
result = read(cookie, value);
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
|
96
|
+
// Prevent storing a cookie that we couldn't decode.
|
97
|
+
if (!key && (cookie = read(cookie)) !== undefined) {
|
98
|
+
result[name] = cookie;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
return result;
|
103
|
+
};
|
104
|
+
|
105
|
+
config.defaults = {};
|
106
|
+
|
107
|
+
$.removeCookie = function (key, options) {
|
108
|
+
if ($.cookie(key) === undefined) {
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
|
112
|
+
// Must not alter options, thus extending a fresh object...
|
113
|
+
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
|
114
|
+
return !$.cookie(key);
|
115
|
+
};
|
116
|
+
|
117
|
+
}));
|