I have this legacy app which is 98% PHP with a smattering of JS. I'm trying to make it a little more dynamic and user-friendly by buffing up the JS, but I'm running into issues in how JS treats the data coming from PHP. It keeps trashing the sort order and I haven't been able to figure out how to stop/repair it. My PHP data is an associative array called $events that looks like this:
Array
(
[4972] => Array
(
[event_id] => 4972
[event_name] => Setup
[event_start_date] => 2018-02-05 08:00:00
[event_end_date] => 2018-02-16 16:00:00
[event_parent] => 4972
[event_milestone] => 0
[event_dynamic] => 1
[event_order] => 1
[root_event] => 1
[child_count] => 3
[dep_start_date] => 2018-02-16 16:00:00
[child_event_1] => 4975
[child_event_2] => 4973
[child_event_3] => 4974
)
[4975] => Array
(
[event_id] => 4975
[event_name] => Seating
[event_start_date] => 2018-02-05 08:00:00
[event_end_date] => 2018-02-09 16:00:00
[event_parent] => 4972
[event_milestone] => 0
[event_dynamic] => 0
[event_order] => 2
[root_event] =>
[child_count] => 0
[dep_start_date] => 2018-02-09 16:00:00
)
[4973] => Array
(
[event_id] => 4973
[event_name] => Stage
[event_start_date] => 2018-02-12 08:00:00
[event_end_date] => 2018-02-14 16:00:00
[event_parent] => 4972
[event_milestone] => 0
[event_dynamic] => 0
[event_order] => 3
[root_event] =>
[child_count] => 0
[dep_start_date] => 2018-02-14 16:00:00
)
[4974] => Array
(
[event_id] => 4974
[event_name] => Refreshments
[event_start_date] => 2018-02-15 08:00:00
[event_end_date] => 2018-02-16 16:00:00
[event_parent] => 4972
[event_milestone] => 0
[event_dynamic] => 0
[event_order] => 4
[root_event] =>
[child_count] => 0
[dep_start_date] => 2018-02-16 16:00:00
)
[4896] => Array
(
[event_id] => 4896
[event_name] => Week 1
[event_start_date] => 2018-02-19 08:00:00
[event_end_date] => 2018-02-23 16:00:00
[event_parent] => 4896
[event_milestone] => 0
[event_dynamic] => 1
[event_order] => 5
[root_event] => 1
[child_count] => 2
[dep_start_date] => 2018-02-23 16:00:00
[child_event_1] => 4897
[child_event_2] => 4898
)
[4897] => Array
(
[event_id] => 4897
[event_name] => Session 1
[event_start_date] => 2018-02-19 08:00:00
[event_end_date] => 2018-02-21 16:00:00
[event_parent] => 4896
[event_milestone] => 0
[event_dynamic] => 0
[event_order] => 6
[root_event] =>
[child_count] => 0
[dep_start_date] => 2018-02-21 16:00:00
)
[4898] => Array
(
[event_id] => 4898
[event_name] => Session 2
[event_start_date] => 2018-02-22 08:00:00
[event_end_date] => 2018-02-23 16:00:00
[event_parent] => 4896
[event_milestone] => 0
[event_dynamic] => 0
[event_order] => 7
[root_event] =>
[child_count] => 0
[dep_start_date] => 2018-02-23 16:00:00
)
)
The data is used for a variety of functions, but it needs to stay in order because it is used to populate a option list. I prep it for JS with json_encode like this.
$events = json_encode($events);
Then I toss that over the wall to JS with an echo statement and json.parse which makes a JS object.
var events = '<?php echo $events; ?>';
events = JSON.parse(events);
When I look at the data after the echo, it's still the same as the PHP version, but the order is changed after the parse. They appear to be ordered by event_id, which is the key for the object. (I won't take up space by posting the data again. Suffice to say "Week 1" and it's children are first with "Setup" and it's children following. I will post the data if asked.)
I know that JS objects don't really have an order, so I found several answers here that said it needed to be in an array to maintain the order, so I tried this:
var events = [<?php echo $events; ?>];
and then this:
var events = '<?php echo $events; ?>';
events = [events];
events = JSON.parse(events);
neither of which made any difference at all. The sorting was still trashed. So I tried sorting it after the parse. I added values to the event_order field to work with. I read and tried several different versions of this ranging from the simple:
events.sort((a, b) => a.event_order - b.event_order);
to the more complex:
var sort = function (prop, arr) {
prop = prop.split('.');
var len = prop.length;
arr.sort(function (a, b) {
var i = 0;
while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; }
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
});
return arr;
};
sort('events.event_order', events);
which didn't change anything either. So I tried writing it to a new, supposedly sorted, object with this:
var events_sorted = {};
Object
.keys(events).sort(function(a, b){
return events[a].event_order - events[b].event_order;
})
.forEach(function(key) {
events_sorted[key] = events[key];
});
The new object was mangled too.
I've run out of ideas and tried so many things that I'm losing track of what I did and didn't do. I feel like I'm either doing something fundamentally wrong or I'm missing some small detail that's derailing me. Hoping someone can help. Thanks.