copy_tuner_client 0.3.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +2 -2
- data/app/assets/javascripts/copyray.js +477 -0
- data/app/assets/stylesheets/copyray.css +86 -64
- data/app/views/_copy_tuner_bar.html.erb +2 -2
- data/coffeelint.json +135 -0
- data/lib/copy_tuner_client/copyray_middleware.rb +1 -1
- data/lib/copy_tuner_client/version.rb +1 -1
- data/package-lock.json +12 -0
- data/package.json +14 -0
- data/src/copyray.coffee +354 -0
- metadata +7 -3
- data/app/assets/javascripts/copyray.js.coffee +0 -282
data/src/copyray.coffee
ADDED
@@ -0,0 +1,354 @@
|
|
1
|
+
window.Copyray ?= {}
|
2
|
+
|
3
|
+
# Max CSS z-index. The overlay and copyray bar use this.
|
4
|
+
MAX_ZINDEX = 2147483647
|
5
|
+
HIDDEN_CLASS = 'copy-tuner-hidden'
|
6
|
+
|
7
|
+
isMac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
|
8
|
+
|
9
|
+
isVisible = (element) ->
|
10
|
+
!!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)
|
11
|
+
|
12
|
+
getOffset = (elment) ->
|
13
|
+
box = elment.getBoundingClientRect()
|
14
|
+
{
|
15
|
+
top: box.top + window.pageYOffset - document.documentElement.clientTop,
|
16
|
+
left: box.left + window.pageXOffset - document.documentElement.clientLeft
|
17
|
+
}
|
18
|
+
|
19
|
+
# Returns all currently created Copyray.Specimen objects.
|
20
|
+
Copyray.specimens = ->
|
21
|
+
Copyray.BlurbSpecimen.all
|
22
|
+
|
23
|
+
# Looks up the stored constructor info
|
24
|
+
Copyray.constructorInfo = (constructor) ->
|
25
|
+
if window.CopyrayPaths
|
26
|
+
for own info, func of window.CopyrayPaths
|
27
|
+
return JSON.parse(info) if func == constructor
|
28
|
+
null
|
29
|
+
|
30
|
+
getAllComments = (rootElement) ->
|
31
|
+
filterNone = ->
|
32
|
+
NodeFilter.FILTER_ACCEPT
|
33
|
+
|
34
|
+
comments = []
|
35
|
+
iterator = document.createNodeIterator(rootElement, NodeFilter.SHOW_COMMENT, filterNone, false)
|
36
|
+
while (curNode = iterator.nextNode())
|
37
|
+
comments.push(curNode)
|
38
|
+
comments
|
39
|
+
|
40
|
+
# Scans the document for blurbs, creating Copyray.BlurbSpecimen for them.
|
41
|
+
Copyray.findBlurbs = -> util.bm 'findBlurbs', ->
|
42
|
+
# Find all <!-- COPYRAY START ... --> comments
|
43
|
+
comments = getAllComments(document.body).filter((comment) ->
|
44
|
+
comment.nodeValue.startsWith('COPYRAY START')
|
45
|
+
)
|
46
|
+
|
47
|
+
comments.forEach((comment) ->
|
48
|
+
[_, id, path, url] = comment.nodeValue.match(/^COPYRAY START (\d+) (\S*) (\S*)/)
|
49
|
+
blurbElement = null
|
50
|
+
el = comment.nextSibling
|
51
|
+
until !el or (el.nodeType == Node.COMMENT_NODE and el.data == "COPYRAY END #{id}")
|
52
|
+
if el.nodeType == Node.ELEMENT_NODE and el.tagName != 'SCRIPT'
|
53
|
+
blurbElement = el
|
54
|
+
break
|
55
|
+
el = el.nextSibling
|
56
|
+
|
57
|
+
# Remove COPYRAY template comments from the DOM.
|
58
|
+
el.parentNode.removeChild(el) if el?.nodeType == Node.COMMENT_NODE
|
59
|
+
comment.parentNode.removeChild(comment)
|
60
|
+
|
61
|
+
if blurbElement
|
62
|
+
# Add the template specimen
|
63
|
+
Copyray.BlurbSpecimen.add blurbElement,
|
64
|
+
name: path.split('/').slice(-1)[0]
|
65
|
+
path: path
|
66
|
+
url: url
|
67
|
+
)
|
68
|
+
|
69
|
+
# Open the given filesystem path by calling out to Copyray's server.
|
70
|
+
Copyray.open = (url) ->
|
71
|
+
window.open(url, null, 'width=700, height=600')
|
72
|
+
|
73
|
+
# Show the Copyray overlay
|
74
|
+
Copyray.show = (type = null) ->
|
75
|
+
Copyray.Overlay.instance().show(type)
|
76
|
+
Copyray.showBar()
|
77
|
+
|
78
|
+
# Hide the Copyray overlay
|
79
|
+
Copyray.hide = ->
|
80
|
+
Copyray.Overlay.instance().hide()
|
81
|
+
Copyray.hideBar()
|
82
|
+
|
83
|
+
Copyray.addToggleButton = ->
|
84
|
+
element = document.createElement('a')
|
85
|
+
element.addEventListener('click', () ->
|
86
|
+
Copyray.show()
|
87
|
+
)
|
88
|
+
element.classList.add('copyray-toggle-button')
|
89
|
+
element.textContent = 'Open CopyTuner'
|
90
|
+
document.body.appendChild(element)
|
91
|
+
|
92
|
+
# Wraps a DOM element that Copyray is tracking. This is subclassed by
|
93
|
+
# Copyray.Blurbsspecimen
|
94
|
+
class Copyray.Specimen
|
95
|
+
@add: (el, info = {}) ->
|
96
|
+
@all.push new this(el, info)
|
97
|
+
|
98
|
+
@remove: (el) ->
|
99
|
+
@find(el)?.remove()
|
100
|
+
|
101
|
+
@find: (el) ->
|
102
|
+
for specimen in @all
|
103
|
+
return specimen if specimen.el == el
|
104
|
+
null
|
105
|
+
|
106
|
+
@reset: ->
|
107
|
+
@all = []
|
108
|
+
|
109
|
+
constructor: (el, info = {}) ->
|
110
|
+
@el = el
|
111
|
+
@name = info.name
|
112
|
+
@path = info.path
|
113
|
+
@url = info.url
|
114
|
+
|
115
|
+
remove: ->
|
116
|
+
idx = @constructor.all.indexOf(this)
|
117
|
+
@constructor.all.splice(idx, 1) unless idx == -1
|
118
|
+
|
119
|
+
makeBox: ->
|
120
|
+
@bounds = util.computeBoundingBox([@el])
|
121
|
+
@box = document.createElement('div')
|
122
|
+
@box.classList.add('copyray-specimen')
|
123
|
+
@box.classList.add(@constructor.name)
|
124
|
+
for key, value of @bounds
|
125
|
+
@box.style[key] = "#{value}px"
|
126
|
+
|
127
|
+
# If the element is fixed, override the computed position with the fixed one.
|
128
|
+
if getComputedStyle(@el).position == 'fixed'
|
129
|
+
@box.css
|
130
|
+
position : 'fixed'
|
131
|
+
top : getComputedStyle(@el).top
|
132
|
+
left : getComputedStyle(@el).left
|
133
|
+
|
134
|
+
@box.addEventListener('click', =>
|
135
|
+
Copyray.open "#{@url}/blurbs/#{@path}/edit"
|
136
|
+
)
|
137
|
+
|
138
|
+
@box.appendChild(@makeLabel())
|
139
|
+
|
140
|
+
makeLabel: =>
|
141
|
+
div = document.createElement('div')
|
142
|
+
div.classList.add('copyray-specimen-handle')
|
143
|
+
div.classList.add(@constructor.name)
|
144
|
+
div.textContent = @name
|
145
|
+
div
|
146
|
+
|
147
|
+
# copy-tuner blurbs
|
148
|
+
class Copyray.BlurbSpecimen extends Copyray.Specimen
|
149
|
+
@all = []
|
150
|
+
|
151
|
+
# Singleton class for the Copyray "overlay" invoked by the keyboard shortcut
|
152
|
+
class Copyray.Overlay
|
153
|
+
@instance: ->
|
154
|
+
@singletonInstance ||= new this
|
155
|
+
|
156
|
+
constructor: ->
|
157
|
+
Copyray.Overlay.singletonInstance = this
|
158
|
+
@overlay = document.createElement('div')
|
159
|
+
@overlay.setAttribute('id', 'copyray-overlay')
|
160
|
+
@shownBoxes = []
|
161
|
+
@overlay.addEventListener('click', () =>
|
162
|
+
@hide()
|
163
|
+
)
|
164
|
+
|
165
|
+
show: (type = null) ->
|
166
|
+
@reset()
|
167
|
+
Copyray.isShowing = true
|
168
|
+
util.bm 'show', =>
|
169
|
+
unless document.body.contains(@overlay)
|
170
|
+
document.body.appendChild(@overlay)
|
171
|
+
Copyray.findBlurbs()
|
172
|
+
specimens = Copyray.specimens()
|
173
|
+
|
174
|
+
for element in specimens
|
175
|
+
element.makeBox()
|
176
|
+
# A cheap way to "order" the boxes, where boxes positioned closer to the
|
177
|
+
# bottom right of the document have a higher z-index.
|
178
|
+
element.box.style.zIndex = Math.ceil(MAX_ZINDEX*0.9 + element.bounds.top + element.bounds.left)
|
179
|
+
@shownBoxes.push element.box
|
180
|
+
document.body.appendChild(element.box)
|
181
|
+
|
182
|
+
reset: ->
|
183
|
+
$box.remove() for $box in @shownBoxes
|
184
|
+
@shownBoxes = []
|
185
|
+
|
186
|
+
hide: ->
|
187
|
+
Copyray.isShowing = false
|
188
|
+
@overlay.remove()
|
189
|
+
@reset()
|
190
|
+
Copyray.hideBar()
|
191
|
+
|
192
|
+
# Utility methods.
|
193
|
+
util =
|
194
|
+
# Benchmark a piece of code
|
195
|
+
bm: (name, fn) ->
|
196
|
+
time = new Date
|
197
|
+
result = fn()
|
198
|
+
# console.log "#{name} : #{new Date() - time}ms"
|
199
|
+
result
|
200
|
+
|
201
|
+
# elements with no parent in the set.
|
202
|
+
computeBoundingBox: (elements) ->
|
203
|
+
# Edge case: the container may not physically wrap its children, for
|
204
|
+
# example if they are floated and no clearfix is present.
|
205
|
+
if elements.length == 1 and elements[0].clientHeight
|
206
|
+
return util.computeBoundingBox(elements[0].children)
|
207
|
+
|
208
|
+
boxFrame =
|
209
|
+
top : Number.POSITIVE_INFINITY
|
210
|
+
left : Number.POSITIVE_INFINITY
|
211
|
+
right : Number.NEGATIVE_INFINITY
|
212
|
+
bottom : Number.NEGATIVE_INFINITY
|
213
|
+
|
214
|
+
elements.forEach((element) ->
|
215
|
+
return unless isVisible(element)
|
216
|
+
frame = getOffset(element)
|
217
|
+
frame.right = frame.left + element.offsetWidth
|
218
|
+
frame.bottom = frame.top + element.offsetHeight
|
219
|
+
boxFrame.top = frame.top if frame.top < boxFrame.top
|
220
|
+
boxFrame.left = frame.left if frame.left < boxFrame.left
|
221
|
+
boxFrame.right = frame.right if frame.right > boxFrame.right
|
222
|
+
boxFrame.bottom = frame.bottom if frame.bottom > boxFrame.bottom
|
223
|
+
)
|
224
|
+
|
225
|
+
return {
|
226
|
+
left : boxFrame.left
|
227
|
+
top : boxFrame.top
|
228
|
+
width : boxFrame.right - boxFrame.left
|
229
|
+
height : boxFrame.bottom - boxFrame.top
|
230
|
+
}
|
231
|
+
|
232
|
+
Copyray.showBar = ->
|
233
|
+
document.getElementById('copy-tuner-bar').classList.remove(HIDDEN_CLASS)
|
234
|
+
document.querySelector('.copyray-toggle-button').classList.add(HIDDEN_CLASS)
|
235
|
+
Copyray.focusSearchBox()
|
236
|
+
|
237
|
+
Copyray.hideBar = ->
|
238
|
+
document.getElementById('copy-tuner-bar').classList.add(HIDDEN_CLASS)
|
239
|
+
document.querySelector('.copyray-toggle-button').classList.remove(HIDDEN_CLASS)
|
240
|
+
document.querySelector('.js-copy-tuner-bar-log-menu').classList.add(HIDDEN_CLASS)
|
241
|
+
|
242
|
+
Copyray.createLogMenu = ->
|
243
|
+
tbody = document.querySelector('.js-copy-tuner-bar-log-menu__tbody.is-not-initialized')
|
244
|
+
return unless tbody
|
245
|
+
|
246
|
+
tbody.classList.remove('is-not-initialized')
|
247
|
+
baseUrl = document.getElementById('copy-tuner-data').dataset.copyTunerUrl
|
248
|
+
log = JSON.parse(document.getElementById('copy-tuner-data').dataset.copyTunerTranslationLog)
|
249
|
+
|
250
|
+
Object.keys(log).sort().forEach((key) ->
|
251
|
+
value = log[key]
|
252
|
+
return if value == ''
|
253
|
+
|
254
|
+
url = "#{baseUrl}/blurbs/#{key}/edit"
|
255
|
+
|
256
|
+
td1 = document.createElement('td')
|
257
|
+
td1.textContent = key
|
258
|
+
|
259
|
+
td2 = document.createElement('td')
|
260
|
+
td2.textContent = value
|
261
|
+
|
262
|
+
tr = document.createElement('tr')
|
263
|
+
tr.classList.add('copy-tuner-bar-log-menu__row')
|
264
|
+
tr.classList.add('js-copy-tuner-blurb-row')
|
265
|
+
tr.dataset.url = url
|
266
|
+
|
267
|
+
tr.addEventListener('click', ({currentTarget}) ->
|
268
|
+
Copyray.open(currentTarget.dataset.url)
|
269
|
+
)
|
270
|
+
|
271
|
+
tr.appendChild(td1)
|
272
|
+
tr.appendChild(td2)
|
273
|
+
tbody.appendChild(tr)
|
274
|
+
)
|
275
|
+
|
276
|
+
Copyray.focusSearchBox = ->
|
277
|
+
document.querySelector('.js-copy-tuner-bar-search').focus()
|
278
|
+
|
279
|
+
Copyray.toggleLogMenu = ->
|
280
|
+
Copyray.createLogMenu()
|
281
|
+
document.getElementById('copy-tuner-bar-log-menu').classList.toggle(HIDDEN_CLASS)
|
282
|
+
|
283
|
+
Copyray.setupLogMenu = ->
|
284
|
+
element = document.querySelector('.js-copy-tuner-bar-open-log')
|
285
|
+
element.addEventListener('click', (event) ->
|
286
|
+
event.preventDefault()
|
287
|
+
Copyray.toggleLogMenu()
|
288
|
+
)
|
289
|
+
|
290
|
+
Copyray.setupSearchBar = ->
|
291
|
+
timer = null
|
292
|
+
lastKeyword = ''
|
293
|
+
barElement = document.querySelector('.js-copy-tuner-bar-search')
|
294
|
+
|
295
|
+
barElement.addEventListener('focus', ({target}) ->
|
296
|
+
lastKeyword = target.value
|
297
|
+
)
|
298
|
+
|
299
|
+
barElement.addEventListener('keyup', ({target}) ->
|
300
|
+
keyword = target.value.trim()
|
301
|
+
if lastKeyword != keyword
|
302
|
+
Copyray.toggleLogMenu() if !isVisible(document.getElementById('copy-tuner-bar-log-menu'))
|
303
|
+
clearTimeout(timer)
|
304
|
+
timer = setTimeout ->
|
305
|
+
rows = Array.from(document.getElementsByClassName('js-copy-tuner-blurb-row'))
|
306
|
+
if keyword == ''
|
307
|
+
rows.forEach((row) ->
|
308
|
+
row.classList.remove(HIDDEN_CLASS)
|
309
|
+
)
|
310
|
+
else
|
311
|
+
rows.forEach((row) ->
|
312
|
+
row.classList.add(HIDDEN_CLASS)
|
313
|
+
)
|
314
|
+
|
315
|
+
rows.filter((row) ->
|
316
|
+
Array.from(row.getElementsByTagName('td')).some((td) ->
|
317
|
+
td.textContent.includes(keyword)
|
318
|
+
)
|
319
|
+
).forEach((row) ->
|
320
|
+
row.classList.remove(HIDDEN_CLASS)
|
321
|
+
)
|
322
|
+
, 500
|
323
|
+
lastKeyword = keyword
|
324
|
+
)
|
325
|
+
|
326
|
+
init = ->
|
327
|
+
return if Copyray.initialized
|
328
|
+
Copyray.initialized = true
|
329
|
+
|
330
|
+
# Register keyboard shortcuts
|
331
|
+
document.addEventListener('keydown', (event) ->
|
332
|
+
# cmd + shift + k
|
333
|
+
if (isMac and event.metaKey or !isMac and event.ctrlKey) and event.shiftKey and event.keyCode is 75
|
334
|
+
if Copyray.isShowing then Copyray.hide() else Copyray.show()
|
335
|
+
if Copyray.isShowing and event.keyCode is 27 # esc
|
336
|
+
Copyray.hide()
|
337
|
+
)
|
338
|
+
|
339
|
+
# Instantiate the overlay singleton.
|
340
|
+
new Copyray.Overlay
|
341
|
+
# Go ahead and do a pass on the DOM to find templates.
|
342
|
+
Copyray.findBlurbs()
|
343
|
+
|
344
|
+
Copyray.addToggleButton()
|
345
|
+
Copyray.setupSearchBar()
|
346
|
+
Copyray.setupLogMenu()
|
347
|
+
|
348
|
+
# Ready to rock.
|
349
|
+
console?.log "Ready to Copyray. Press #{if isMac then 'cmd+shift+k' else 'ctrl+shift+k'} to scan your UI."
|
350
|
+
|
351
|
+
if document.readyState == 'complete' || document.readyState != 'loading'
|
352
|
+
init()
|
353
|
+
else
|
354
|
+
document.addEventListener('DOMContentLoaded', init)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: copy_tuner_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SonicGarden
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -236,9 +236,10 @@ files:
|
|
236
236
|
- Gemfile.lock
|
237
237
|
- README.md
|
238
238
|
- Rakefile
|
239
|
-
- app/assets/javascripts/copyray.js
|
239
|
+
- app/assets/javascripts/copyray.js
|
240
240
|
- app/assets/stylesheets/copyray.css
|
241
241
|
- app/views/_copy_tuner_bar.html.erb
|
242
|
+
- coffeelint.json
|
242
243
|
- copy_tuner_client.gemspec
|
243
244
|
- features/rails.feature
|
244
245
|
- features/step_definitions/copycopter_server_steps.rb
|
@@ -267,6 +268,8 @@ files:
|
|
267
268
|
- lib/copy_tuner_client/translation_log.rb
|
268
269
|
- lib/copy_tuner_client/version.rb
|
269
270
|
- lib/tasks/copy_tuner_client_tasks.rake
|
271
|
+
- package-lock.json
|
272
|
+
- package.json
|
270
273
|
- spec/copy_tuner_client/cache_spec.rb
|
271
274
|
- spec/copy_tuner_client/client_spec.rb
|
272
275
|
- spec/copy_tuner_client/configuration_spec.rb
|
@@ -288,6 +291,7 @@ files:
|
|
288
291
|
- spec/support/fake_unicorn.rb
|
289
292
|
- spec/support/middleware_stack.rb
|
290
293
|
- spec/support/writing_cache.rb
|
294
|
+
- src/copyray.coffee
|
291
295
|
- ui/views/copytuner/index.html.erb
|
292
296
|
- ui/views/layouts/copytuner_default.html.erb
|
293
297
|
homepage: https://github.com/SonicGarden/copy-tuner-ruby-client
|
@@ -1,282 +0,0 @@
|
|
1
|
-
window.Copyray = {}
|
2
|
-
return unless $ = window.jQuery
|
3
|
-
|
4
|
-
# Max CSS z-index. The overlay and copyray bar use this.
|
5
|
-
MAX_ZINDEX = 2147483647
|
6
|
-
|
7
|
-
# Initialize Copyray. Called immediately, but some setup is deferred until DOM ready.
|
8
|
-
Copyray.init = do ->
|
9
|
-
return if Copyray.initialized
|
10
|
-
Copyray.initialized = true
|
11
|
-
|
12
|
-
is_mac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
|
13
|
-
|
14
|
-
# Register keyboard shortcuts
|
15
|
-
$(document).keydown (e) ->
|
16
|
-
# cmd + shift + k
|
17
|
-
if (is_mac and e.metaKey or !is_mac and e.ctrlKey) and e.shiftKey and e.keyCode is 75
|
18
|
-
if Copyray.isShowing then Copyray.hide() else Copyray.show()
|
19
|
-
if Copyray.isShowing and e.keyCode is 27 # esc
|
20
|
-
Copyray.hide()
|
21
|
-
|
22
|
-
$ ->
|
23
|
-
# Instantiate the overlay singleton.
|
24
|
-
new Copyray.Overlay
|
25
|
-
# Go ahead and do a pass on the DOM to find templates.
|
26
|
-
Copyray.findBlurbs()
|
27
|
-
|
28
|
-
Copyray.addToggleButton()
|
29
|
-
|
30
|
-
# Ready to rock.
|
31
|
-
console?.log "Ready to Copyray. Press #{if is_mac then 'cmd+shift+k' else 'ctrl+shift+k'} to scan your UI."
|
32
|
-
|
33
|
-
# Returns all currently created Copyray.Specimen objects.
|
34
|
-
Copyray.specimens = ->
|
35
|
-
Copyray.BlurbSpecimen.all
|
36
|
-
|
37
|
-
# Looks up the stored constructor info
|
38
|
-
Copyray.constructorInfo = (constructor) ->
|
39
|
-
if window.CopyrayPaths
|
40
|
-
for own info, func of window.CopyrayPaths
|
41
|
-
return JSON.parse(info) if func == constructor
|
42
|
-
null
|
43
|
-
|
44
|
-
# Scans the document for blurbs, creating Copyray.BlurbSpecimen for them.
|
45
|
-
Copyray.findBlurbs = -> util.bm 'findBlurbs', ->
|
46
|
-
# Find all <!-- COPYRAY START ... --> comments
|
47
|
-
comments = $('*:not(iframe,script)').contents().filter ->
|
48
|
-
this.nodeType == 8 and this.data[0..12] == "COPYRAY START"
|
49
|
-
|
50
|
-
# Find the <!-- COPYRAY END ... --> comment for each. Everything between the
|
51
|
-
for comment in comments
|
52
|
-
[_, id, path, url] = comment.data.match(/^COPYRAY START (\d+) (\S*) (\S*)/)
|
53
|
-
$blurbContents = new jQuery
|
54
|
-
el = comment.nextSibling
|
55
|
-
until !el or (el.nodeType == 8 and el.data == "COPYRAY END #{id}")
|
56
|
-
if el.nodeType == 1 and el.tagName != 'SCRIPT'
|
57
|
-
$blurbContents.push el
|
58
|
-
el = el.nextSibling
|
59
|
-
# Remove COPYRAY template comments from the DOM.
|
60
|
-
el.parentNode.removeChild(el) if el?.nodeType == 8
|
61
|
-
comment.parentNode.removeChild(comment)
|
62
|
-
# Add the template specimen
|
63
|
-
Copyray.BlurbSpecimen.add $blurbContents,
|
64
|
-
name: path.split('/').slice(-1)[0]
|
65
|
-
path: path
|
66
|
-
url: url
|
67
|
-
|
68
|
-
# Open the given filesystem path by calling out to Copyray's server.
|
69
|
-
Copyray.open = (url) ->
|
70
|
-
window.open(url, null, 'width=700, height=600')
|
71
|
-
|
72
|
-
# Show the Copyray overlay
|
73
|
-
Copyray.show = (type = null) ->
|
74
|
-
Copyray.Overlay.instance().show(type)
|
75
|
-
Copyray.showBar()
|
76
|
-
|
77
|
-
# Hide the Copyray overlay
|
78
|
-
Copyray.hide = ->
|
79
|
-
Copyray.Overlay.instance().hide()
|
80
|
-
Copyray.hideBar()
|
81
|
-
|
82
|
-
Copyray.toggleSettings = ->
|
83
|
-
Copyray.Overlay.instance().settings.toggle()
|
84
|
-
|
85
|
-
Copyray.addToggleButton = ->
|
86
|
-
$('body').append("<a href='javascript:Copyray.show()' class='copyray-toggle-button'>Open CopyTuner</a>")
|
87
|
-
|
88
|
-
# Wraps a DOM element that Copyray is tracking. This is subclassed by
|
89
|
-
# Copyray.Blurbsspecimen
|
90
|
-
class Copyray.Specimen
|
91
|
-
@add: (el, info = {}) ->
|
92
|
-
@all.push new this(el, info)
|
93
|
-
|
94
|
-
@remove: (el) ->
|
95
|
-
@find(el)?.remove()
|
96
|
-
|
97
|
-
@find: (el) ->
|
98
|
-
el = el[0] if el instanceof jQuery
|
99
|
-
for specimen in @all
|
100
|
-
return specimen if specimen.el == el
|
101
|
-
null
|
102
|
-
|
103
|
-
@reset: ->
|
104
|
-
@all = []
|
105
|
-
|
106
|
-
constructor: (contents, info = {}) ->
|
107
|
-
@el = if contents instanceof jQuery then contents[0] else contents
|
108
|
-
@$contents = $(contents)
|
109
|
-
@name = info.name
|
110
|
-
@path = info.path
|
111
|
-
@url = info.url
|
112
|
-
|
113
|
-
remove: ->
|
114
|
-
idx = @constructor.all.indexOf(this)
|
115
|
-
@constructor.all.splice(idx, 1) unless idx == -1
|
116
|
-
|
117
|
-
isVisible: ->
|
118
|
-
@$contents.length
|
119
|
-
|
120
|
-
makeBox: ->
|
121
|
-
@bounds = util.computeBoundingBox(@$contents)
|
122
|
-
@$box = $("<div class='copyray-specimen #{@constructor.name}'>").css(@bounds)
|
123
|
-
|
124
|
-
# If the element is fixed, override the computed position with the fixed one.
|
125
|
-
if @$contents.css('position') == 'fixed'
|
126
|
-
@$box.css
|
127
|
-
position : 'fixed'
|
128
|
-
top : @$contents.css('top')
|
129
|
-
left : @$contents.css('left')
|
130
|
-
|
131
|
-
@$box.click => Copyray.open @url + '/blurbs/' + @path + '/edit'
|
132
|
-
@$box.append @makeLabel
|
133
|
-
|
134
|
-
makeLabel: =>
|
135
|
-
$("<div class='copyray-specimen-handle #{@constructor.name}'>").append(@name)
|
136
|
-
|
137
|
-
# copy-tuner blurbs
|
138
|
-
class Copyray.BlurbSpecimen extends Copyray.Specimen
|
139
|
-
@all = []
|
140
|
-
|
141
|
-
# Singleton class for the Copyray "overlay" invoked by the keyboard shortcut
|
142
|
-
class Copyray.Overlay
|
143
|
-
@instance: ->
|
144
|
-
@singletonInstance ||= new this
|
145
|
-
|
146
|
-
constructor: ->
|
147
|
-
Copyray.Overlay.singletonInstance = this
|
148
|
-
@$overlay = $('<div id="copyray-overlay">')
|
149
|
-
@shownBoxes = []
|
150
|
-
@$overlay.click => @hide()
|
151
|
-
|
152
|
-
show: (type = null) ->
|
153
|
-
@reset()
|
154
|
-
Copyray.isShowing = true
|
155
|
-
util.bm 'show', =>
|
156
|
-
unless @$overlay.is(':visible')
|
157
|
-
$('body').append @$overlay
|
158
|
-
Copyray.findBlurbs()
|
159
|
-
specimens = Copyray.specimens()
|
160
|
-
for element in specimens
|
161
|
-
continue unless element.isVisible()
|
162
|
-
element.makeBox()
|
163
|
-
# A cheap way to "order" the boxes, where boxes positioned closer to the
|
164
|
-
# bottom right of the document have a higher z-index.
|
165
|
-
element.$box.css
|
166
|
-
zIndex: Math.ceil(MAX_ZINDEX*0.9 + element.bounds.top + element.bounds.left)
|
167
|
-
@shownBoxes.push element.$box
|
168
|
-
$('body').append element.$box
|
169
|
-
|
170
|
-
reset: ->
|
171
|
-
$box.remove() for $box in @shownBoxes
|
172
|
-
@shownBoxes = []
|
173
|
-
|
174
|
-
hide: ->
|
175
|
-
Copyray.isShowing = false
|
176
|
-
@$overlay.detach()
|
177
|
-
@reset()
|
178
|
-
Copyray.hideBar()
|
179
|
-
|
180
|
-
# Utility methods.
|
181
|
-
util =
|
182
|
-
# Benchmark a piece of code
|
183
|
-
bm: (name, fn) ->
|
184
|
-
time = new Date
|
185
|
-
result = fn()
|
186
|
-
# console.log "#{name} : #{new Date() - time}ms"
|
187
|
-
result
|
188
|
-
|
189
|
-
# Computes the bounding box of a jQuery set, which may be many sibling
|
190
|
-
# elements with no parent in the set.
|
191
|
-
computeBoundingBox: ($contents) ->
|
192
|
-
# Edge case: the container may not physically wrap its children, for
|
193
|
-
# example if they are floated and no clearfix is present.
|
194
|
-
if $contents.length == 1 and $contents.height() <= 0
|
195
|
-
return util.computeBoundingBox($contents.children())
|
196
|
-
|
197
|
-
boxFrame =
|
198
|
-
top : Number.POSITIVE_INFINITY
|
199
|
-
left : Number.POSITIVE_INFINITY
|
200
|
-
right : Number.NEGATIVE_INFINITY
|
201
|
-
bottom : Number.NEGATIVE_INFINITY
|
202
|
-
|
203
|
-
for el in $contents
|
204
|
-
$el = $(el)
|
205
|
-
continue unless $el.is(':visible')
|
206
|
-
frame = $el.offset()
|
207
|
-
frame.right = frame.left + $el.outerWidth()
|
208
|
-
frame.bottom = frame.top + $el.outerHeight()
|
209
|
-
boxFrame.top = frame.top if frame.top < boxFrame.top
|
210
|
-
boxFrame.left = frame.left if frame.left < boxFrame.left
|
211
|
-
boxFrame.right = frame.right if frame.right > boxFrame.right
|
212
|
-
boxFrame.bottom = frame.bottom if frame.bottom > boxFrame.bottom
|
213
|
-
|
214
|
-
return {
|
215
|
-
left : boxFrame.left
|
216
|
-
top : boxFrame.top
|
217
|
-
width : boxFrame.right - boxFrame.left
|
218
|
-
height : boxFrame.bottom - boxFrame.top
|
219
|
-
}
|
220
|
-
|
221
|
-
Copyray.showBar = ->
|
222
|
-
$('#copy-tuner-bar').show()
|
223
|
-
$('.copyray-toggle-button').hide()
|
224
|
-
Copyray.focusSearchBox()
|
225
|
-
|
226
|
-
Copyray.hideBar = ->
|
227
|
-
$('#copy-tuner-bar').hide()
|
228
|
-
$('.copyray-toggle-button').show()
|
229
|
-
$('.js-copy-tuner-bar-log-menu').hide()
|
230
|
-
|
231
|
-
Copyray.createLogMenu = ->
|
232
|
-
$tbody = $('.js-copy-tuner-bar-log-menu__tbody.is-not-initialized')
|
233
|
-
return if $tbody.length == 0
|
234
|
-
$tbody.removeClass('is-not-initialized')
|
235
|
-
baseUrl = $('[data-copy-tuner-url]').data('copy-tuner-url')
|
236
|
-
log = $('[data-copy-tuner-translation-log').data('copy-tuner-translation-log')
|
237
|
-
keys = Object.keys(log).sort()
|
238
|
-
$.each keys, (_, k) ->
|
239
|
-
v = log[k]
|
240
|
-
if v != ''
|
241
|
-
url = "#{baseUrl}/blurbs/#{k}/edit"
|
242
|
-
$a = $("<a href='#{url}' class='js-copy-tuner-blurb-link'>").text k
|
243
|
-
$td1 = $('<td>').append $a
|
244
|
-
$td2 = $('<td>').text v
|
245
|
-
$tr = $("<tr class='copy-tuner-bar-log-menu__row js-copy-tuner-blurb-row'>")
|
246
|
-
$tr.append $td1, $td2
|
247
|
-
$tbody.append $tr
|
248
|
-
$tbody.on 'click', '.js-copy-tuner-blurb-link', (e) ->
|
249
|
-
e.preventDefault()
|
250
|
-
$tbody.on 'click', '.js-copy-tuner-blurb-row', ->
|
251
|
-
Copyray.open $(@).find('a').attr('href')
|
252
|
-
|
253
|
-
Copyray.focusSearchBox = ->
|
254
|
-
$('.js-copy-tuner-bar-search').focus()
|
255
|
-
|
256
|
-
Copyray.toggleLogMenu = ->
|
257
|
-
Copyray.createLogMenu()
|
258
|
-
$('.js-copy-tuner-bar-log-menu').toggle()
|
259
|
-
|
260
|
-
$(document).on 'click', '.js-copy-tuner-bar-open-log', (e) ->
|
261
|
-
e.preventDefault()
|
262
|
-
Copyray.toggleLogMenu()
|
263
|
-
|
264
|
-
do ->
|
265
|
-
timer = null
|
266
|
-
lastKeyword = ''
|
267
|
-
$(document).on 'focus', '.js-copy-tuner-bar-search', ->
|
268
|
-
lastKeyword = $(@).val()
|
269
|
-
$(document).on 'keyup', '.js-copy-tuner-bar-search', ->
|
270
|
-
keyword = $.trim($(@).val())
|
271
|
-
if lastKeyword != keyword
|
272
|
-
Copyray.toggleLogMenu() if !$('.js-copy-tuner-bar-log-menu').is(':visible')
|
273
|
-
clearTimeout(timer)
|
274
|
-
timer = setTimeout ->
|
275
|
-
if keyword == ''
|
276
|
-
$('.js-copy-tuner-blurb-row').show()
|
277
|
-
else
|
278
|
-
$('.js-copy-tuner-blurb-row').hide()
|
279
|
-
$(".js-copy-tuner-blurb-row td:contains(#{keyword})").closest('.js-copy-tuner-blurb-row').show()
|
280
|
-
, 500
|
281
|
-
lastKeyword = keyword
|
282
|
-
|