diff --git a/light9/effect/sequencer.html b/light9/effect/sequencer.html
--- a/light9/effect/sequencer.html
+++ b/light9/effect/sequencer.html
@@ -115,9 +115,15 @@
const height = Math.min(40, dt / 0.025 * 20);
return `height: ${height}px;`
});
+
+ const fakeUris = (report.songNotes || []).map((obj) => { return {value: obj.note, orig: obj} });
+ const s = this.graph.sortedUris(fakeUris);
+ report.songNotes = s.map((u) => { return u.orig; });
+
(report.songNotes || []).forEach((note) => {
note.rowClass = note.nonZero ? 'active' : 'inactive';
note.effectSettingsPairs = [];
+
const attrs = Object.keys(note.effectSettings);
attrs.sort();
attrs.forEach((attr) => {
diff --git a/light9/web/graph.coffee b/light9/web/graph.coffee
--- a/light9/web/graph.coffee
+++ b/light9/web/graph.coffee
@@ -371,3 +371,12 @@ class window.SyncedGraph
ctxs.push(q.graph)
return _.unique(ctxs)
+ sortedUris: (uris) ->
+ _.sortBy uris, (u) ->
+ parts = u.value.split(/([0-9]+)/)
+ expanded = parts.map (p) ->
+ f = parseInt(p)
+ return p if isNaN(f)
+ return p.padStart(8, '0')
+ return expanded.join('')
+
\ No newline at end of file
diff --git a/light9/web/live/live.coffee b/light9/web/live/live.coffee
--- a/light9/web/live/live.coffee
+++ b/light9/web/live/live.coffee
@@ -59,7 +59,7 @@ coffeeElementSetup(class Light9LiveDevic
@deviceClass = @graph.uriValue(@uri, U('rdf:type'))
@deviceAttrs = []
- for da in _.unique(_.sortBy(@graph.objects(@deviceClass, U(':deviceAttr'))))
+ for da in _.unique(@graph.sortedUris(@graph.objects(@deviceClass, U(':deviceAttr'))))
dataType = @graph.uriValue(da, U(':dataType'))
daRow = {
uri: da
@@ -71,7 +71,7 @@ coffeeElementSetup(class Light9LiveDevic
else if dataType.equals(U(':choice'))
daRow.useChoice = true
- choiceUris = _.sortBy(@graph.objects(da, U(':choice')))
+ choiceUris = @graph.sortedUris(@graph.objects(da, U(':choice')))
daRow.choices = ({uri: x, label: @graph.labelOrTail(x)} for x in choiceUris)
daRow.choiceSize = Math.min(choiceUris.length + 1, 10)
else
@@ -191,8 +191,8 @@ coffeeElementSetup(class Light9LiveContr
U = (x) => @graph.Uri(x)
@set('devices', [])
- for dc in _.sortBy(@graph.subjects(U('rdf:type'), U(':DeviceClass')))
- for dev in _.sortBy(@graph.subjects(U('rdf:type'), dc))
+ for dc in @graph.sortedUris(@graph.subjects(U('rdf:type'), U(':DeviceClass')))
+ for dev in @graph.sortedUris(@graph.subjects(U('rdf:type'), dc))
@push('devices', {uri: dev})
return
diff --git a/light9/web/timeline/timeline.coffee b/light9/web/timeline/timeline.coffee
--- a/light9/web/timeline/timeline.coffee
+++ b/light9/web/timeline/timeline.coffee
@@ -355,7 +355,7 @@ coffeeElementSetup(class TimeZoomed exte
toRemove = new Set(@noteByUriStr.keys())
- for uri in _.sortBy(songNotes, 'id')
+ for uri in @graph.sortedUris(songNotes)
had = toRemove.delete(uri.value)
if not had
@_addNote(uri)