adva 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/adva.gemspec +0 -1
- data/app/assets/javascripts/adva_cms/table_tree.js +517 -0
- data/app/assets/javascripts/adva_cms.js +1 -1
- data/app/assets/stylesheets/adva_cms/admin/tooltip.scss +10 -0
- data/app/assets/stylesheets/adva_cms/admin.scss +1 -1
- data/app/controllers/admin/sections_controller.rb +1 -1
- data/lib/adva/version.rb +1 -1
- data/lib/adva.rb +0 -1
- metadata +4 -32
- data/app/assets/javascripts/adva_cms/jquery.table_tree.js +0 -704
- data/app/assets/stylesheets/adva_cms/jquery/alternate/jquery.tooltip.scss +0 -13
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_222222_256x240.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_2e83ff_256x240.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_454545_256x240.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_888888_256x240.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/app/assets/stylesheets/adva_cms/jquery/jquery.tooltip.scss +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cf3ba6c659842798c42f6fd015bb0d54fad9dd565bb63fc323bc8c615369f4d
|
4
|
+
data.tar.gz: 0e0c7ada44b479f0dbb1ad5c66d893c499e58ec3943c799d9a83011838af9423
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a15cfe13315178e1c85398203a36a0123f4f9e722cec84945f8586ac70219f0273e191e057a28dcf14d197b1673f29595ed071ce045fee07c5774f6bb4bdd54
|
7
|
+
data.tar.gz: effc8e38738625656411470277a71032c3b5b549d34a785316d8edd7d9c4f3c342aef404bf26e7ae182fc92ed713e7b10d65bca8c11c8468999a60f727ef9070
|
data/adva.gemspec
CHANGED
@@ -0,0 +1,517 @@
|
|
1
|
+
document.addEventListener("DOMContentLoaded", () => {
|
2
|
+
const table = document.querySelector("table.list")
|
3
|
+
const link = document.querySelector("a.reorder")
|
4
|
+
if(table && link) new TableTree(table, link)
|
5
|
+
})
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Configuration options:
|
9
|
+
*
|
10
|
+
* onDragClass
|
11
|
+
* This class is added for the duration of the drag and then removed when the row is dropped. It is more
|
12
|
+
* flexible than using onDragStyle since it can be inherited by the row cells and other content. The default
|
13
|
+
* is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your
|
14
|
+
* stylesheet.
|
15
|
+
* onDrop
|
16
|
+
* Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table
|
17
|
+
* and the row that was dropped. You can work out the new order of the rows by using
|
18
|
+
* table.rows.
|
19
|
+
* onDragStart
|
20
|
+
* Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the
|
21
|
+
* table and the row which the user has started to drag.
|
22
|
+
* onAllowDrop
|
23
|
+
* Pass a function that will be called as a row is over another row. If the function returns true, allow
|
24
|
+
* dropping on that row, otherwise not. The function takes 2 parameters: the dragged row and the row under
|
25
|
+
* the cursor. It returns a boolean: true allows the drop, false doesn't allow it.
|
26
|
+
* scrollAmount
|
27
|
+
* This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the
|
28
|
+
* window. The page should automatically scroll up or down as appropriate.
|
29
|
+
*/
|
30
|
+
|
31
|
+
class TableDnD {
|
32
|
+
constructor() {
|
33
|
+
this.currentTable = null
|
34
|
+
this.dragObject = null
|
35
|
+
this.mouseOffset = null
|
36
|
+
this.oldY = 0
|
37
|
+
}
|
38
|
+
|
39
|
+
add(table, options) {
|
40
|
+
table.tableDnDConfig = {
|
41
|
+
// Add in the default class for whileDragging
|
42
|
+
onDragClass: "tDnD_whileDrag",
|
43
|
+
onDrop: null,
|
44
|
+
onDrag: null, // ADDED
|
45
|
+
onDragStart: null,
|
46
|
+
scrollAmount: 5,
|
47
|
+
...(options || {}),
|
48
|
+
}
|
49
|
+
this.makeDraggable(table)
|
50
|
+
}
|
51
|
+
|
52
|
+
makeDraggable(table) {
|
53
|
+
table.querySelectorAll("tr").forEach(row => {
|
54
|
+
row.addEventListener("mousedown", event => this.mousedown(table, row, event))
|
55
|
+
row.style.cursor = "move"
|
56
|
+
})
|
57
|
+
// Now we need to capture the mouse up and mouse move event
|
58
|
+
// We can use bind so that we don't interfere with other event handlers
|
59
|
+
document.addEventListener('mousemove', event => this.mousemove(event))
|
60
|
+
document.addEventListener('mouseup', event => this.mouseup(event))
|
61
|
+
}
|
62
|
+
|
63
|
+
mousedown(table, row, event) {
|
64
|
+
if(event.target.tagName == "TD") {
|
65
|
+
event.preventDefault()
|
66
|
+
this.dragObject = row
|
67
|
+
this.currentTable = table
|
68
|
+
this.mouseOffset = this.getMouseOffset(row, event)
|
69
|
+
let config = table.tableDnDConfig
|
70
|
+
if(config.onDragStart) config.onDragStart(table, row)
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
/** Given a target element and a mouse event, get the mouse offset from that element.
|
75
|
+
To do this we need the element's position and the mouse position */
|
76
|
+
getMouseOffset(target, event) {
|
77
|
+
var docPos = this.getPosition(target)
|
78
|
+
return {
|
79
|
+
x: event.pageX - docPos.x,
|
80
|
+
y: event.pageY - docPos.y,
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
getPosition(element) {
|
85
|
+
const rect = element.getBoundingClientRect()
|
86
|
+
return {
|
87
|
+
x: rect.left + window.pageXOffset,
|
88
|
+
y: rect.top + window.pageYOffset,
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
mousemove(event) {
|
93
|
+
if (this.dragObject == null) {
|
94
|
+
return
|
95
|
+
}
|
96
|
+
|
97
|
+
var config = this.currentTable.tableDnDConfig
|
98
|
+
var y = event.pageY - this.mouseOffset.y
|
99
|
+
var yOffset = window.pageYOffset
|
100
|
+
if (event.pageY - yOffset < config.scrollAmount) {
|
101
|
+
window.scrollBy(0, -config.scrollAmount)
|
102
|
+
} else if(window.innerHeight - (event.pageY-yOffset) < config.scrollAmount) {
|
103
|
+
window.scrollBy(0, config.scrollAmount)
|
104
|
+
}
|
105
|
+
|
106
|
+
if (y != this.oldY) {
|
107
|
+
// work out if we're going up or down...
|
108
|
+
var movingDown = y > this.oldY
|
109
|
+
this.oldY = y
|
110
|
+
this.dragObject.classList.add(config.onDragClass)
|
111
|
+
// If we're over a row then move the dragged row to there so that the user sees the
|
112
|
+
// effect dynamically
|
113
|
+
var currentRow = this.findDropTargetRow(this.dragObject, y, movingDown)
|
114
|
+
if(currentRow) {
|
115
|
+
if (movingDown && this.dragObject != currentRow) {
|
116
|
+
this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling)
|
117
|
+
} else if(!movingDown && this.dragObject != currentRow) {
|
118
|
+
this.dragObject.parentNode.insertBefore(this.dragObject, currentRow)
|
119
|
+
}
|
120
|
+
if(config.onDrag) {
|
121
|
+
config.onDrag(this.currentTable, this.dragObject)
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
return false
|
126
|
+
}
|
127
|
+
|
128
|
+
/** We're only worried about the y position really, because we can only move rows up and down */
|
129
|
+
findDropTargetRow(draggedRow, y, movingDown) {
|
130
|
+
const rows = Array.from(this.currentTable.querySelectorAll("tr"))
|
131
|
+
for (var i=0; i<rows.length; i++) {
|
132
|
+
var row = rows[i]
|
133
|
+
var rowY = this.getPosition(row).y
|
134
|
+
var rowHeight = parseInt(row.offsetHeight)/2
|
135
|
+
if (row.offsetHeight == 0) {
|
136
|
+
rowY = this.getPosition(row.firstChild).y
|
137
|
+
rowHeight = parseInt(row.firstChild.offsetHeight)/2
|
138
|
+
}
|
139
|
+
// Because we always have to insert before, we need to offset the height a bit
|
140
|
+
if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
|
141
|
+
// that's the row we're over
|
142
|
+
// If it's the same as the current row, ignore it
|
143
|
+
if(row == draggedRow) return
|
144
|
+
var config = this.currentTable.tableDnDConfig
|
145
|
+
if (config.onAllowDrop) {
|
146
|
+
if(!config.onAllowDrop(draggedRow, row, movingDown)) return
|
147
|
+
}
|
148
|
+
return row
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
mouseup(e) {
|
154
|
+
if(this.currentTable && this.dragObject) {
|
155
|
+
var droppedRow = this.dragObject
|
156
|
+
var config = this.currentTable.tableDnDConfig
|
157
|
+
// If we have a dragObject, then we need to release it,
|
158
|
+
// The row will already have been moved to the right place so we just reset stuff
|
159
|
+
droppedRow.classList.remove(config.onDragClass)
|
160
|
+
this.dragObject = null
|
161
|
+
if(config.onDrop) config.onDrop(this.currentTable, droppedRow)
|
162
|
+
this.currentTable = null; // let go of the table too
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
teardown(table) {
|
167
|
+
table.querySelectorAll("tr").forEach(row => {
|
168
|
+
row.removeEventListener("mousedown", event => this.mousedown(table, row, event))
|
169
|
+
row.style.cursor = "auto"
|
170
|
+
})
|
171
|
+
this.dragObject = null
|
172
|
+
this.currentTable = null
|
173
|
+
this.mouseOffset = null
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
class Base {
|
178
|
+
find_node(element) {
|
179
|
+
for (var i = 0; i < this.children.length; i++) {
|
180
|
+
var child = this.children[i]
|
181
|
+
if (this.children[i].element == element) {
|
182
|
+
return this.children[i]
|
183
|
+
} else {
|
184
|
+
var result = this.children[i].find_node(element)
|
185
|
+
if (result) return result
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
ttnode(node) {
|
191
|
+
var subject = node.push ? node[0] : node
|
192
|
+
return (this.current_table || this.table_tree.current_table).find_node(subject)
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
class TableTree extends Base {
|
197
|
+
constructor(table, link) {
|
198
|
+
super()
|
199
|
+
this.table = table
|
200
|
+
this.type = link.id.replace('reorder_', '')
|
201
|
+
this.collection_url = link.href
|
202
|
+
this.tableDnD = new TableDnD()
|
203
|
+
|
204
|
+
link.addEventListener("click", event => {
|
205
|
+
event.preventDefault()
|
206
|
+
link.parentElement.classList.toggle('active')
|
207
|
+
this.toggle()
|
208
|
+
})
|
209
|
+
|
210
|
+
this.tableDnDOptions = {
|
211
|
+
onDragClass: 'drag',
|
212
|
+
onDragStart: (table, row) => {
|
213
|
+
this.startOffset = this.tableDnD.mouseOffset.x
|
214
|
+
row.addEventListener("mousemove", event => this.mousemove(event))
|
215
|
+
this.ttnode(row)?.dragStart()
|
216
|
+
},
|
217
|
+
onDrag: (table, row) => {
|
218
|
+
this.current_table.dirty = true
|
219
|
+
this.ttnode(row)?.update_children()
|
220
|
+
},
|
221
|
+
onDrop: (table, row) => {
|
222
|
+
row.removeEventListener("mousemove", event => this.mousemove(event))
|
223
|
+
this.ttnode(row)?.drop()
|
224
|
+
this.current_table.rebuild()
|
225
|
+
this.current_table.update_remote(row)
|
226
|
+
},
|
227
|
+
onAllowDrop: (draggedRow, row, movingDown) => {
|
228
|
+
const node = this.ttnode(row)
|
229
|
+
const next = movingDown ? node.next_row_sibling() : node
|
230
|
+
if(next && next.parent && this.ttnode(draggedRow)) {
|
231
|
+
if(next.parent.level >= this.ttnode(draggedRow).level) return false
|
232
|
+
}
|
233
|
+
return node ? true : false
|
234
|
+
}
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
toggle() {
|
239
|
+
this.current_table ? this.teardown() : this.setup()
|
240
|
+
}
|
241
|
+
|
242
|
+
setup() {
|
243
|
+
const tbody = this.table.querySelector('tbody')
|
244
|
+
this.tableDnD.add(tbody, this.tableDnDOptions)
|
245
|
+
this.current_table = new Table(this, this.table, this.type, this.collection_url)
|
246
|
+
this.current_table.setSortable()
|
247
|
+
}
|
248
|
+
|
249
|
+
teardown() {
|
250
|
+
// this.current_table.update_remote()
|
251
|
+
this.tableDnD.teardown(this.table)
|
252
|
+
this.current_table.setUnsortable()
|
253
|
+
this.current_table = null
|
254
|
+
}
|
255
|
+
|
256
|
+
level(element) {
|
257
|
+
var match = element.className.match(/level_([\d]+)/)
|
258
|
+
return match ? parseInt(match[1]) : 0
|
259
|
+
}
|
260
|
+
|
261
|
+
mousemove(event) {
|
262
|
+
if (!this.current_table.is_tree) return
|
263
|
+
|
264
|
+
const element = event.target.closest("tr")
|
265
|
+
const offset = this.tableDnD.getMouseOffset(element, event).x - this.startOffset
|
266
|
+
if(offset > 25) {
|
267
|
+
this.current_table.dirty = true
|
268
|
+
this.ttnode(element).increment_level(event)
|
269
|
+
} else if(offset < -25) {
|
270
|
+
this.current_table.dirty = true
|
271
|
+
this.ttnode(element).decrement_level(event)
|
272
|
+
}
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
class Table extends Base {
|
277
|
+
constructor(table_tree, table, type, collection_url) {
|
278
|
+
super()
|
279
|
+
this.table_tree = table_tree
|
280
|
+
this.is_tree = table.classList.contains('tree')
|
281
|
+
this.table = table
|
282
|
+
this.type = type
|
283
|
+
this.level = -1
|
284
|
+
this.collection_url = collection_url
|
285
|
+
this.rebuild()
|
286
|
+
}
|
287
|
+
|
288
|
+
rebuild() {
|
289
|
+
this.trs = Array.from(this.table.querySelectorAll('tr'))
|
290
|
+
this.children = this.trs.map(tr => {
|
291
|
+
if(this.table_tree.level(tr) === 0) {
|
292
|
+
return new Node(this.table_tree, this, tr, this.table_tree.level(tr))
|
293
|
+
}
|
294
|
+
}).filter(e => e)
|
295
|
+
}
|
296
|
+
|
297
|
+
setSortable() {
|
298
|
+
this.trs.forEach(tr => {
|
299
|
+
// tr is in thead
|
300
|
+
let cells = tr.querySelectorAll('th')
|
301
|
+
cells.forEach((th, index) => {
|
302
|
+
if(index === 0) {
|
303
|
+
th.setAttribute('colspan', cells.length)
|
304
|
+
} else {
|
305
|
+
th.hidden = true
|
306
|
+
}
|
307
|
+
})
|
308
|
+
|
309
|
+
// tbody
|
310
|
+
cells = tr.querySelectorAll('td')
|
311
|
+
cells.forEach((td, index) => {
|
312
|
+
if (index === 0) {
|
313
|
+
td.setAttribute('colspan', cells.length)
|
314
|
+
td.querySelectorAll('a').forEach((a, index) => {
|
315
|
+
a.hidden = true
|
316
|
+
if (index === 0) {
|
317
|
+
td.appendChild(document.createTextNode(a.innerText))
|
318
|
+
}
|
319
|
+
})
|
320
|
+
} else {
|
321
|
+
td.hidden = true
|
322
|
+
}
|
323
|
+
})
|
324
|
+
})
|
325
|
+
}
|
326
|
+
|
327
|
+
setUnsortable() {
|
328
|
+
this.trs.forEach(tr => {
|
329
|
+
// tr is in thead
|
330
|
+
let cells = tr.querySelectorAll('th')
|
331
|
+
cells.forEach((th, index) => {
|
332
|
+
if(index === 0) {
|
333
|
+
this.setAttribute('colspan', 1)
|
334
|
+
} else {
|
335
|
+
th.hidden = false
|
336
|
+
}
|
337
|
+
})
|
338
|
+
|
339
|
+
// tbody
|
340
|
+
cells = tr.querySelectorAll('td')
|
341
|
+
cells.forEach((td, index) => {
|
342
|
+
if (index === 0) {
|
343
|
+
td.querySelectorAll('a').forEach((a, index) => {
|
344
|
+
a.hidden = false
|
345
|
+
if (index === 0) {
|
346
|
+
td.removeChild(td.lastChild)
|
347
|
+
}
|
348
|
+
})
|
349
|
+
td.querySelector('img.spinner')?.remove()
|
350
|
+
td.setAttribute('colspan', 1)
|
351
|
+
} else {
|
352
|
+
td.hidden = false
|
353
|
+
}
|
354
|
+
})
|
355
|
+
})
|
356
|
+
}
|
357
|
+
|
358
|
+
update_remote(row) {
|
359
|
+
if(!this.dirty) return
|
360
|
+
this.dirty = false
|
361
|
+
this.show_spinner(row)
|
362
|
+
|
363
|
+
fetch(this.collection_url, {
|
364
|
+
method: "PUT",
|
365
|
+
body: new URLSearchParams({
|
366
|
+
...this.serialize(row),
|
367
|
+
authenticity_token: window._auth_token,
|
368
|
+
}),
|
369
|
+
})
|
370
|
+
.then(() => this.hide_spinner(row))
|
371
|
+
.catch(() => this.hide_spinner(row))
|
372
|
+
}
|
373
|
+
|
374
|
+
serialize(row) {
|
375
|
+
row = this.ttnode(row)
|
376
|
+
let data = {}
|
377
|
+
data[`${this.type}[${row.id()}][parent_id]`] = row.parent_id()
|
378
|
+
data[`${this.type}[${row.id()}][left_id]`] = row.left_id()
|
379
|
+
return data
|
380
|
+
}
|
381
|
+
|
382
|
+
show_spinner(row) {
|
383
|
+
let img = document.createElement('img')
|
384
|
+
img.src = 'data:image/gif;base64,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'
|
385
|
+
img.className = 'spinner'
|
386
|
+
row.querySelector("td").appendChild(img)
|
387
|
+
}
|
388
|
+
|
389
|
+
hide_spinner(row) {
|
390
|
+
let cell = row.querySelector('td')
|
391
|
+
cell.removeChild(cell.lastChild)
|
392
|
+
}
|
393
|
+
}
|
394
|
+
|
395
|
+
class Node extends Base {
|
396
|
+
constructor(table_tree, parent, element, level) {
|
397
|
+
super()
|
398
|
+
this.table_tree = table_tree
|
399
|
+
this.parent = parent
|
400
|
+
this.element = element
|
401
|
+
this.level = level
|
402
|
+
|
403
|
+
this.children = this.find_children().map(child => {
|
404
|
+
var level = this.table_tree.level(child)
|
405
|
+
if(level == this.level + 1) {
|
406
|
+
return new Node(this.table_tree, this, child, level)
|
407
|
+
}
|
408
|
+
}).filter(e => e)
|
409
|
+
}
|
410
|
+
|
411
|
+
find_children() {
|
412
|
+
var stop = false
|
413
|
+
return this.row_siblings().slice(this.row_index() + 1).filter(child => {
|
414
|
+
var level = this.table_tree.level(child)
|
415
|
+
if(this.level == level) stop = true // how to break from an iterator?
|
416
|
+
return !stop && this.level + 1 == level
|
417
|
+
})
|
418
|
+
}
|
419
|
+
|
420
|
+
depth() {
|
421
|
+
if (this.children.length > 0) {
|
422
|
+
return Math.max.apply(Math, this.children.map(child => child.depth()))
|
423
|
+
} else {
|
424
|
+
return this.level
|
425
|
+
}
|
426
|
+
}
|
427
|
+
|
428
|
+
siblings() {
|
429
|
+
return this.parent.children
|
430
|
+
}
|
431
|
+
|
432
|
+
id() {
|
433
|
+
return this.element ? this.to_int(this.element.id) : 'null'
|
434
|
+
}
|
435
|
+
|
436
|
+
parent_id() {
|
437
|
+
return this.parent.element ? this.to_int(this.parent.element.id) : 'null'
|
438
|
+
}
|
439
|
+
|
440
|
+
left_id() {
|
441
|
+
let left = this.left()
|
442
|
+
return left ? this.to_int(left.element.id) : 'null'
|
443
|
+
}
|
444
|
+
|
445
|
+
left() {
|
446
|
+
let siblings = this.siblings()
|
447
|
+
let ix = siblings.indexOf(this) - 1
|
448
|
+
if(ix >= 0) return siblings[ix]
|
449
|
+
}
|
450
|
+
|
451
|
+
to_int(str) {
|
452
|
+
if(str) return str.replace(/[\D]+/, '')
|
453
|
+
}
|
454
|
+
|
455
|
+
next_row_sibling() {
|
456
|
+
return this.row_siblings()[this.row_index() + 1]
|
457
|
+
}
|
458
|
+
|
459
|
+
row_siblings() {
|
460
|
+
this._row_siblings ||= Array.from(this.element.parentElement.children)
|
461
|
+
return this._row_siblings
|
462
|
+
}
|
463
|
+
|
464
|
+
row_index() {
|
465
|
+
return this.row_siblings().indexOf(this.element)
|
466
|
+
}
|
467
|
+
|
468
|
+
dragStart() {
|
469
|
+
this.element.classList.add('drag')
|
470
|
+
this.children.forEach(child => child.dragStart())
|
471
|
+
}
|
472
|
+
|
473
|
+
drop() {
|
474
|
+
this.element.classList.remove('drag')
|
475
|
+
this.children.forEach(child => child.drop())
|
476
|
+
this.adjust_level()
|
477
|
+
}
|
478
|
+
|
479
|
+
increment_level(event) {
|
480
|
+
let prev = this.element.previousElementSibling
|
481
|
+
if(prev) prev = this.ttnode(prev)
|
482
|
+
if(!prev || prev.level < this.level || this.depth() >= 5) return
|
483
|
+
this.update_level(event, this.level + 1)
|
484
|
+
}
|
485
|
+
|
486
|
+
decrement_level(event) {
|
487
|
+
if(this.level == 0) return
|
488
|
+
this.update_level(event, this.level - 1)
|
489
|
+
}
|
490
|
+
|
491
|
+
update_level(event, level) {
|
492
|
+
if (event) this.table_tree.startOffset = this.table_tree.tableDnD.getMouseOffset(this.element, event).x
|
493
|
+
|
494
|
+
this.element.classList.remove('level_' + this.level)
|
495
|
+
this.element.classList.add('level_' + level)
|
496
|
+
|
497
|
+
this.level = level
|
498
|
+
this.children.forEach(child => child.update_level(event, level + 1))
|
499
|
+
}
|
500
|
+
|
501
|
+
adjust_level() {
|
502
|
+
var prev = this.element.previousElementSibling
|
503
|
+
if(!prev) {
|
504
|
+
this.update_level(null, 0)
|
505
|
+
} else if(this.ttnode(prev).level + 1 < this.level) {
|
506
|
+
this.update_level(null, this.ttnode(prev).level + 1)
|
507
|
+
}
|
508
|
+
}
|
509
|
+
|
510
|
+
update_children() {
|
511
|
+
this.children.forEach(child => child.element.parentNode.removeChild(child.element))
|
512
|
+
var next = this.element.nextSibling
|
513
|
+
this.children.forEach(child => this.element.parentNode.insertBefore(child.element, next))
|
514
|
+
this.children.forEach(child => child.update_children())
|
515
|
+
}
|
516
|
+
}
|
517
|
+
|
@@ -11,5 +11,5 @@
|
|
11
11
|
//= require "adva_cms/admin/helptip.css"
|
12
12
|
//= require "adva_cms/admin/users.css"
|
13
13
|
//= require "adva_cms/admin/activities.css"
|
14
|
-
//= require "adva_cms/
|
14
|
+
//= require "adva_cms/admin/tooltip.css"
|
15
15
|
//= require "adva_cms/admin/projection.css"
|
@@ -52,7 +52,7 @@ class Admin::SectionsController < Admin::BaseController
|
|
52
52
|
parent = Section.find_by(id: attrs[:parent_id])
|
53
53
|
left = Section.find_by_id attrs[:left_id]
|
54
54
|
if parent
|
55
|
-
|
55
|
+
section.move_to_child_with_index parent, 0
|
56
56
|
else
|
57
57
|
section.move_to_root
|
58
58
|
section.move_to_left_of section.siblings.first
|
data/lib/adva/version.rb
CHANGED
data/lib/adva.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adva
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Micah Geisel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: will_paginate
|
@@ -122,20 +122,6 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: jquery-rails
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
125
|
description: Adva CMS
|
140
126
|
email:
|
141
127
|
- micah@botandrose.com
|
@@ -255,7 +241,7 @@ files:
|
|
255
241
|
- app/assets/javascripts/adva_cms.js
|
256
242
|
- app/assets/javascripts/adva_cms/ckeditor.js.erb
|
257
243
|
- app/assets/javascripts/adva_cms/concat_main_menus.js
|
258
|
-
- app/assets/javascripts/adva_cms/
|
244
|
+
- app/assets/javascripts/adva_cms/table_tree.js
|
259
245
|
- app/assets/javascripts/ckeditor/config.js.erb
|
260
246
|
- app/assets/stylesheets/admin.scss
|
261
247
|
- app/assets/stylesheets/adva_cms/admin.scss
|
@@ -279,26 +265,12 @@ files:
|
|
279
265
|
- app/assets/stylesheets/adva_cms/admin/screen/top.scss
|
280
266
|
- app/assets/stylesheets/adva_cms/admin/sidebar.scss
|
281
267
|
- app/assets/stylesheets/adva_cms/admin/themes.scss
|
268
|
+
- app/assets/stylesheets/adva_cms/admin/tooltip.scss
|
282
269
|
- app/assets/stylesheets/adva_cms/admin/top.scss
|
283
270
|
- app/assets/stylesheets/adva_cms/admin/users.scss
|
284
271
|
- app/assets/stylesheets/adva_cms/common.scss
|
285
272
|
- app/assets/stylesheets/adva_cms/default.scss
|
286
273
|
- app/assets/stylesheets/adva_cms/forms.scss
|
287
|
-
- app/assets/stylesheets/adva_cms/jquery/alternate/jquery.tooltip.scss
|
288
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png
|
289
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_flat_75_ffffff_40x100.png
|
290
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png
|
291
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_65_ffffff_1x400.png
|
292
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_75_dadada_1x400.png
|
293
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png
|
294
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_95_fef1ec_1x400.png
|
295
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png
|
296
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-icons_222222_256x240.png
|
297
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-icons_2e83ff_256x240.png
|
298
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-icons_454545_256x240.png
|
299
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-icons_888888_256x240.png
|
300
|
-
- app/assets/stylesheets/adva_cms/jquery/images/ui-icons_cd0a0a_256x240.png
|
301
|
-
- app/assets/stylesheets/adva_cms/jquery/jquery.tooltip.scss
|
302
274
|
- app/assets/stylesheets/adva_cms/layout/login.scss
|
303
275
|
- app/assets/stylesheets/adva_cms/layout/simple.scss
|
304
276
|
- app/assets/stylesheets/adva_cms/menu.scss
|