help-anywhere 0.1.3 → 0.1.4b

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.
data/README.rdoc CHANGED
@@ -36,11 +36,62 @@ See help-anywhere-example project for more information!
36
36
 
37
37
  Log-in has edit mode, and create new help page with our editor. Enjoy!
38
38
 
39
+ == Require authorization for edit mode.
40
+
41
+ If you just follow the steps before, there is no authorization needed to edit the pages and components of your help.
42
+ But you can add it easily:
43
+
44
+ in `yourapp/config/initializers/help_anywhere.rb` just set:
45
+
46
+ HelpAnywhere.configure do |config|
47
+ # Set here the method which is called to allow or disallow edition mode
48
+ # You can create this method in your ApplicationController class.
49
+ # By default, this will always return always true: every one can edit help.
50
+ config.edition_role = :can_user_edit_help?
51
+ end
52
+
53
+
54
+ == Routing the content
55
+
56
+ You can route dynamically for your help resource. A route will match an url with a specific help resource name.
57
+
58
+ Example:
59
+
60
+
61
+ config.routes do |routes|
62
+ routes.match '/articles/*/show...', 'articles#show'
63
+ end
64
+
65
+
66
+ This will allow every resource located at http://mywebsite/articles/xxxx/show(/xxx/yyy/zzz...) to share the same help (here articles#show page).
67
+
68
+ You can use `*` to wilcard a path level, and `...` to wilcard everything after. Samely, you can use `?` and `??` to use it in output:
69
+
70
+ Example:
71
+
72
+ config.routes do |routes|
73
+ routes.match '/?/*/?', '$1#$2' # ex: url /resource/1/edit <=> resource#edit help page
74
+ end
75
+
76
+
77
+ By default, every url create a new help resource. Keep in mind the hash part of the url is not used. For plugins for ajax which use hash part (like jquery-bbq), you need to refine manually the route like this:
78
+
79
+
80
+ $(window).bind( 'hashchange', function(e) {
81
+ //Force help-anywhere to get resource manually
82
+ HelpAnywhere.retrieveResource(HelpAnywhere.selectRoute($.param.fragment()));
83
+ });
84
+
39
85
  == Version
40
86
 
87
+ 0.1.4
88
+
89
+ - Now you can bind a bubble to an element without typing the selector manually. A button provide an interface to select an object into the page.
90
+ You can select anything, but take care about dynamic content (over routes), otherwise your block can be missplaced!
91
+
41
92
  0.1.1
42
93
 
43
94
  - This is the first stable release!
44
95
  - HelpAnywhere is provided with Bubble component, but you can also build your own. Check `app/javascript/bubble.coffee.js`
45
96
  for more informations.
46
- You can ignore this component. Just `require help_anywhere_core_only` in both application.js and .css
97
+ You can ignore this component. Just `require help_anywhere_core_only` in both application.js and .css
data/Rakefile CHANGED
@@ -34,5 +34,8 @@ Rake::TestTask.new(:test) do |t|
34
34
  t.verbose = false
35
35
  end
36
36
 
37
-
38
37
  task :default => :test
38
+
39
+ task :server, [:args] do |t, args|
40
+ exec "cd test/dummy && rails s #{args[:args]}"
41
+ end
@@ -8,6 +8,90 @@
8
8
  Here we code all logic for show and edit mode.
9
9
  ###
10
10
  do ( $ = jQuery ) ->
11
+
12
+ ###
13
+ HTML SELECTION SYSTEM
14
+ ###
15
+ getAbsoluteSelectorFor = (elm) ->
16
+ return '' if elm.get(0).tagName is 'BODY'
17
+
18
+ if (id = elm.attr('id'))?
19
+ return "##{id}"
20
+
21
+ selector = elm.parents().toArray()
22
+ .map (x) ->
23
+ out = x.tagName
24
+ if (id = $(x).attr('id'))?
25
+ out += "##{id}"
26
+ if (classes = $(x).attr('class'))? and classes isnt ''
27
+ out += classes.split(/\s/g).map((x)-> '.' + x).join()
28
+ return out
29
+ .reverse()
30
+ .join('>')
31
+
32
+ selector += ">:nth-child(#{elm.index()+1})"
33
+
34
+ return selector
35
+
36
+ window.HookingSystem =
37
+ currentMouseMoveTarget: null
38
+ enabled: false
39
+
40
+ callback: (selector) ->
41
+
42
+ enable: (callback) ->
43
+ $("#help-anywhere-layout").css display: 'none'
44
+
45
+ @callback = callback
46
+ @enabled = true
47
+ @stopMouseMove = false
48
+
49
+
50
+ handleMouseDown = (evt) ->
51
+ return true unless HookingSystem.enabled
52
+
53
+ HookingSystem.antiClickLayer ?= $('<div>').css(
54
+ position: 'fixed'
55
+ width: '100%'
56
+ height: '100%'
57
+ 'background-color': 'transparent'
58
+ 'z-index': '20001'
59
+ top: '0'
60
+ left: '0'
61
+ )
62
+
63
+ HookingSystem.antiClickLayer.appendTo($('body'))
64
+ HookingSystem.antiClickLayer.on 'mouseup', handleMouseClick
65
+ HookingSystem.stopMouseMove = true
66
+
67
+ handleMouseClick = (evt) ->
68
+ evt.preventDefault()
69
+ evt.stopPropagation()
70
+
71
+ $(HookingSystem.currentMouseMoveTarget).removeClass("ha-hook-hover")
72
+
73
+ HookingSystem.callback(getAbsoluteSelectorFor($(HookingSystem.currentMouseMoveTarget)))
74
+ HookingSystem.enabled = false
75
+
76
+ HookingSystem.antiClickLayer.remove()
77
+
78
+ HookingSystem.antiClickLayer = null
79
+ HookingSystem.currentMouseMoveTarget = null
80
+
81
+ $("#help-anywhere-layout").css display: 'block'
82
+
83
+ handleMouseMove = (evt) ->
84
+ return true unless HookingSystem.enabled and not HookingSystem.stopMouseMove
85
+
86
+ $(HookingSystem.currentMouseMoveTarget).removeClass('ha-hook-hover')
87
+
88
+ $(evt.target).addClass('ha-hook-hover')
89
+
90
+ HookingSystem.currentMouseMoveTarget = evt.target
91
+
92
+ $("html").on 'mousemove', handleMouseMove
93
+ $("html").on 'mousedown', handleMouseDown
94
+
11
95
  BUBBLE_TEMPLATE = -> """
12
96
  <div class="ha-bubble-box">
13
97
  <div class="ha-bubble-pointer"></div>
@@ -31,7 +115,7 @@ do ( $ = jQuery ) ->
31
115
  <option value="guess">Auto</option>
32
116
  </select>
33
117
  Selector:
34
- <input type="text" class="ha-bubble-selector" value="">
118
+ <input type="text" class="ha-bubble-selector" value=""><div class="ha-bubble-select-selector">*</div>
35
119
  <input type="button" class="ha-bubble-remove btn btn-danger" value="Remove">
36
120
  </div>
37
121
  """
@@ -126,7 +210,7 @@ do ( $ = jQuery ) ->
126
210
  docW = parseFloat(documentSize[0])
127
211
  docH = parseFloat(documentSize[1])
128
212
 
129
- unless @position || @position is 'guess' #Guess mode
213
+ if not @position || @position is 'guess' #Guess mode
130
214
  ###
131
215
  x,y-------x2,y
132
216
  | |
@@ -301,6 +385,7 @@ do ( $ = jQuery ) ->
301
385
  .off('mouseup', @handleMouseUpInstance)
302
386
 
303
387
  @elm.remove()
388
+ @targetArea.remove()
304
389
 
305
390
  buildEditMode: ->
306
391
  self = this
@@ -317,17 +402,23 @@ do ( $ = jQuery ) ->
317
402
 
318
403
  @control.find('.ha-bubble-position').on 'change', ->
319
404
  self.position = $(this).val()
320
- self.saveChanges()
321
405
  self.refresh()
406
+ self.saveChanges()
322
407
 
323
408
  @control.find('.ha-bubble-selector').on 'change', ->
324
409
  self.target = $(this).val()
325
- self.saveChanges()
326
410
  self.refresh()
411
+ self.saveChanges()
327
412
 
328
413
  @control.find('.ha-bubble-remove').on 'click', ->
329
414
  HelpAnywhere.deleteItem(self)
330
415
 
416
+ @control.find('.ha-bubble-select-selector').on 'click', ->
417
+ HookingSystem.enable (selector) ->
418
+ self.position = 'auto' if self.position is 'free'
419
+ self.control.find('.ha-bubble-selector').val(selector).trigger('change')
420
+
421
+
331
422
  content = @elm.find('.ha-bubble-content')
332
423
 
333
424
  content
@@ -364,4 +455,6 @@ do ( $ = jQuery ) ->
364
455
  @saveChanges()
365
456
 
366
457
  #Register generator to generators list
367
- HelpAnywhere.Component.register('Bubble', Bubble)
458
+ HelpAnywhere.Component.register('Bubble', Bubble)
459
+
460
+
@@ -63,8 +63,7 @@ do($ = jQuery) ->
63
63
  return true
64
64
  else
65
65
  return false
66
- @hide: ->
67
- @instance.closeHelpInterface()
66
+ @hide: -> @instance.closeHelpInterface()
68
67
  @edit: -> @show(yes)
69
68
 
70
69
  @saveElement: (elm) ->
@@ -84,12 +83,12 @@ do($ = jQuery) ->
84
83
  for [regexp, value] in routes
85
84
  regexp = '^' +
86
85
  regexp
87
- .replace('/', '\\/')
88
- .replace('.', '\\.')
89
- .replace('**', '.*')
90
- .replace('*', '[^\\/]*')
91
- .replace('??', '(.*)')
92
- .replace('?', '([^\\/]*)') + '$'
86
+ .replace(/\//g, '\\/')
87
+ .replace(/\./g, '\\.')
88
+ .replace(/\*/g, '[^\\/]*')
89
+ .replace(/\.\.\./g, '.*') #/[\.]{3}/ ??
90
+ .replace(/\?\?/g, '(.*)')
91
+ .replace(/\?/, '([^\\/]*)') + '$'
93
92
  @routes.push [new RegExp(regexp), value]
94
93
 
95
94
  @deleteItem: (elm) ->
@@ -206,9 +205,13 @@ do($ = jQuery) ->
206
205
  @helpInterface = null
207
206
 
208
207
  openHelpInterface: (@edit_mode=false)->
209
- @helpInterface ?= $ HELP_INTERFACE_TEMPLATE(@pageList, @edit_mode)
208
+ return if @helpInterface?
209
+
210
+ @helpInterface = $ HELP_INTERFACE_TEMPLATE(@pageList, @edit_mode)
210
211
  @helpInterface.appendTo($("body"))
211
212
  @currentPage = 0
213
+ @elementsChanged = false
214
+
212
215
  self = this
213
216
 
214
217
  unless @edit_mode
@@ -1,3 +1,17 @@
1
+ .ha-hook-hover {
2
+ //border: solid 3px orange;
3
+ //box-sizing: border-box;
4
+ box-shadow: inset 0px 0px 0px 3px orange;
5
+ }
6
+
7
+ .ha-bubble-target-selected {
8
+ border: solid 3px orange;
9
+ box-sizing: border-box;
10
+ display: 'block';
11
+ position: absolute;
12
+ }
13
+
14
+
1
15
  .ha-bubble-box {
2
16
  -webkit-touch-callout: none;
3
17
  -webkit-user-select: none;
@@ -125,6 +139,25 @@
125
139
  width: 100%;
126
140
  }
127
141
 
142
+ input.ha-bubble-selector {
143
+ width: 150px;
144
+ float: left;
145
+ }
146
+
147
+ .ha-bubble-select-selector {
148
+ cursor: pointer;
149
+ border: solid 1px white;
150
+ padding: 0px 7px;
151
+ background-color: #DDD;
152
+ font-weight: bold;
153
+ color: #333;
154
+ height: 19px;
155
+ float: right;
156
+ height: 17px;
157
+ margin-top: 2px;
158
+ }
159
+
160
+
128
161
  input {
129
162
  border: solid 1px #EEE;
130
163
  }
@@ -122,18 +122,6 @@
122
122
  }
123
123
  }
124
124
 
125
- .ha-bubble-target-selected {
126
- border: solid 3px orange;
127
- box-sizing: border-box;
128
- display: 'block';
129
- position: absolute;
130
- }
131
-
132
-
133
-
134
- .ha-hover {
135
- box-shadow: inset 0px 0px 1px 1px red, inset 0px 0px 2px 2px white !important;
136
- }
137
125
 
138
126
  #help-anywhere-selectbox {
139
127
  position: absolute;
@@ -50,9 +50,9 @@ module HelpAnywhere
50
50
  self.match_data << [ regexp, result ]
51
51
  end
52
52
 
53
- def ignore regexp
54
- self.ignore_data << [ regexp, result ]
55
- end
53
+ #def ignore regexp
54
+ # self.ignore_data << [ regexp, result ]
55
+ #end
56
56
 
57
57
  def to_json *args
58
58
  arr = self.match_data + DEFAULTS_ROUTES
@@ -1,3 +1,3 @@
1
1
  module HelpAnywhere
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4b"
3
3
  end
@@ -1,4 +1,44 @@
1
- # desc "Explaining what the task does"
2
- # task :help-anywhere do
3
- # # Task goes here
4
- # end
1
+ #coding: utf-8
2
+
3
+ namespace :help_anywhere do
4
+ desc "Generate everything you need to run help-anywhere plugin."
5
+ task :setup => ['help_anywhere:install:migrations'] do
6
+
7
+ relpath = File.join ["config", "initializers", "help_anywhere.rb"]
8
+
9
+ filepath = File.join Dir.pwd, relpath
10
+
11
+ if File.exists?(filepath)
12
+ puts "[X] Skipping `#{relpath}`: File already exists"
13
+ else
14
+ File.write filepath,
15
+ <<-RUBY
16
+ HelpAnywhere.configure do |config|
17
+
18
+ config.routes do |routes|
19
+ # Configure route between help pages and your controllers
20
+ # Use `*` to wilcard a path level, `...` to wilcard everything after
21
+ # and `?` to reuse a path level
22
+ # The second string is just an unique id for your help, you can use
23
+ # whatever you want!
24
+ #
25
+ # Example:
26
+ #
27
+ # routes.match '/articles/*/show...', 'article_show'
28
+ # routes.match '/admin/?/*/?...', 'admin_help_for_resource_$1_action_$2'
29
+ end
30
+
31
+ # Set here the method which is called to alloww or disallow edition mode
32
+ # You can create this method in your ApplicationController class.
33
+ # Default is a method which return always true: every one can edit help.
34
+ #
35
+ # config.edition_role = :can_user_edit_help?
36
+ end
37
+ RUBY
38
+
39
+ puts "[»] create `#{relpath}`"
40
+ end
41
+
42
+ puts "[»] Done! please add `require help_anywhere` in both application.js and application.css, run migrations, enjoy!"
43
+ end
44
+ end
File without changes
File without changes
@@ -0,0 +1,31 @@
1
+ Connecting to database specified by database.yml
2
+ Connecting to database specified by database.yml
3
+ Connecting to database specified by database.yml
4
+
5
+
6
+ Started GET "/" for 127.0.0.1 at 2013-10-02 12:14:24 +0200
7
+
8
+ ActionController::RoutingError (No route matches [GET] "/"):
9
+ actionpack (3.2.13) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
10
+ actionpack (3.2.13) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
11
+ railties (3.2.13) lib/rails/rack/logger.rb:32:in `call_app'
12
+ railties (3.2.13) lib/rails/rack/logger.rb:16:in `block in call'
13
+ activesupport (3.2.13) lib/active_support/tagged_logging.rb:22:in `tagged'
14
+ railties (3.2.13) lib/rails/rack/logger.rb:16:in `call'
15
+ actionpack (3.2.13) lib/action_dispatch/middleware/request_id.rb:22:in `call'
16
+ rack (1.4.5) lib/rack/methodoverride.rb:21:in `call'
17
+ rack (1.4.5) lib/rack/runtime.rb:17:in `call'
18
+ activesupport (3.2.13) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
19
+ rack (1.4.5) lib/rack/lock.rb:15:in `call'
20
+ actionpack (3.2.13) lib/action_dispatch/middleware/static.rb:63:in `call'
21
+ railties (3.2.13) lib/rails/engine.rb:479:in `call'
22
+ railties (3.2.13) lib/rails/application.rb:223:in `call'
23
+ rack (1.4.5) lib/rack/content_length.rb:14:in `call'
24
+ railties (3.2.13) lib/rails/rack/log_tailer.rb:17:in `call'
25
+ rack (1.4.5) lib/rack/handler/webrick.rb:59:in `service'
26
+ /home/yacine/.rvm/rubies/ruby-1.9.3-p362/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
27
+ /home/yacine/.rvm/rubies/ruby-1.9.3-p362/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
28
+ /home/yacine/.rvm/rubies/ruby-1.9.3-p362/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
29
+
30
+
31
+ Rendered /home/yacine/.rvm/gems/ruby-1.9.3-p362/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (4.9ms)
@@ -0,0 +1,11 @@
1
+ Connecting to database specified by database.yml
2
+ Connecting to database specified by database.yml
3
+ Connecting to database specified by database.yml
4
+  (0.5ms) begin transaction
5
+  (0.1ms) rollback transaction
6
+ Connecting to database specified by database.yml
7
+  (0.4ms) begin transaction
8
+  (0.1ms) rollback transaction
9
+ Connecting to database specified by database.yml
10
+  (0.2ms) begin transaction
11
+  (0.1ms) rollback transaction
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: help-anywhere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
5
- prerelease:
4
+ version: 0.1.4b
5
+ prerelease: 5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Yacine Petitprez
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-01 00:00:00.000000000 Z
12
+ date: 2013-10-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.2.13
30
+ - !ruby/object:Gem::Dependency
31
+ name: colorize
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: sqlite3
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -104,6 +120,10 @@ files:
104
120
  - test/dummy/public/404.html
105
121
  - test/dummy/public/500.html
106
122
  - test/dummy/public/422.html
123
+ - test/dummy/db/development.sqlite3
124
+ - test/dummy/db/test.sqlite3
125
+ - test/dummy/log/development.log
126
+ - test/dummy/log/test.log
107
127
  - test/dummy/app/assets/stylesheets/application.css
108
128
  - test/dummy/app/assets/javascripts/application.js
109
129
  - test/dummy/app/views/layouts/application.html.erb
@@ -127,16 +147,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
147
  version: '0'
128
148
  segments:
129
149
  - 0
130
- hash: -1282744831073083889
150
+ hash: 1614212497889084903
131
151
  required_rubygems_version: !ruby/object:Gem::Requirement
132
152
  none: false
133
153
  requirements:
134
- - - ! '>='
154
+ - - ! '>'
135
155
  - !ruby/object:Gem::Version
136
- version: '0'
137
- segments:
138
- - 0
139
- hash: -1282744831073083889
156
+ version: 1.3.1
140
157
  requirements: []
141
158
  rubyforge_project:
142
159
  rubygems_version: 1.8.23
@@ -166,6 +183,10 @@ test_files:
166
183
  - test/dummy/public/404.html
167
184
  - test/dummy/public/500.html
168
185
  - test/dummy/public/422.html
186
+ - test/dummy/db/development.sqlite3
187
+ - test/dummy/db/test.sqlite3
188
+ - test/dummy/log/development.log
189
+ - test/dummy/log/test.log
169
190
  - test/dummy/app/assets/stylesheets/application.css
170
191
  - test/dummy/app/assets/javascripts/application.js
171
192
  - test/dummy/app/views/layouts/application.html.erb