copy_tuner_client 0.3.5 → 0.4.0
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.
- 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
|
-
|