help-anywhere 0.1.3 → 0.1.4b

Sign up to get free protection for your applications and to get access to all the features.
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