From 6c1e3a7410a8814c4690ffb315c6625130d3dddc Mon Sep 17 00:00:00 2001 From: Colin McLeod Date: Wed, 20 May 2015 00:29:24 -0700 Subject: [PATCH] Custom comparisons, performance improvements --- app/{images => }/icons/bin.svg | 0 app/{images => }/icons/cancel-circle.svg | 0 app/{images => }/icons/checkmark.svg | 0 app/{images => }/icons/checkmark2.svg | 0 app/{images => }/icons/cogs.svg | 0 app/{images => }/icons/coriolis.svg | 0 app/{images => }/icons/download.svg | 0 .../arrow-down-left.svg => icons/embed.svg} | 3 +- app/{images => }/icons/floppy-disk.svg | 0 app/{images => }/icons/github-mark.svg | 0 app/{images => }/icons/hammer.svg | 0 app/{images => }/icons/info.svg | 0 app/{images => }/icons/link.svg | 0 .../icons/mount-f.svg => icons/mount-F.svg} | 0 .../icons/mount-g.svg => icons/mount-G.svg} | 0 .../icons/mount-t.svg => icons/mount-T.svg} | 0 app/{images => }/icons/notification.svg | 0 app/{images => }/icons/question.svg | 0 app/{images => }/icons/rocket.svg | 0 app/{images => }/icons/spinner11.svg | 0 app/{images => }/icons/stats-bars.svg | 0 app/{images => }/icons/switch.svg | 0 app/{images => }/icons/upload.svg | 0 app/{images => }/icons/warning.svg | 0 app/images/icons/arrow-down-left2.svg | 6 - app/images/icons/arrow-down-right.svg | 6 - app/images/icons/arrow-down-right2.svg | 6 - app/images/icons/arrow-down.svg | 6 - app/images/icons/arrow-down2.svg | 6 - app/images/icons/arrow-left.svg | 6 - app/images/icons/arrow-left2.svg | 6 - app/images/icons/arrow-right.svg | 6 - app/images/icons/arrow-right2.svg | 6 - app/images/icons/arrow-up-left.svg | 6 - app/images/icons/arrow-up-left2.svg | 6 - app/images/icons/arrow-up-right.svg | 6 - app/images/icons/arrow-up-right2.svg | 6 - app/images/icons/arrow-up.svg | 6 - app/images/icons/arrow-up2.svg | 6 - app/images/icons/blocked.svg | 6 - app/images/icons/checkbox-checked.svg | 6 - app/images/icons/checkbox-unchecked.svg | 6 - app/images/icons/circle-down.svg | 7 - app/images/icons/circle-left.svg | 7 - app/images/icons/circle-right.svg | 7 - app/images/icons/circle-up.svg | 7 - app/images/icons/clipboard.svg | 7 - app/images/icons/cloud-check.svg | 6 - app/images/icons/cloud-download.svg | 6 - app/images/icons/cloud-upload.svg | 6 - app/images/icons/cloud.svg | 6 - app/images/icons/cog.svg | 6 - app/images/icons/coin-dollar.svg | 6 - app/images/icons/cross.svg | 6 - app/images/icons/enlarge.svg | 9 - app/images/icons/enlarge2.svg | 6 - app/images/icons/equalizer.svg | 6 - app/images/icons/equalizer2.svg | 6 - app/images/icons/infinite.svg | 6 - app/images/icons/loop.svg | 6 - app/images/icons/loop2.svg | 7 - app/images/icons/menu.svg | 6 - app/images/icons/menu2.svg | 8 - app/images/icons/menu3.svg | 7 - app/images/icons/menu4.svg | 7 - app/images/icons/meter.svg | 6 - app/images/icons/meter2.svg | 6 - app/images/icons/minus.svg | 6 - app/images/icons/move-down.svg | 15 -- app/images/icons/move-up.svg | 15 -- app/images/icons/pie-chart.svg | 6 - app/images/icons/plus.svg | 6 - app/images/icons/power-cord.svg | 7 - app/images/icons/power.svg | 6 - app/images/icons/radio-checked.svg | 6 - app/images/icons/radio-checked2.svg | 6 - app/images/icons/radio-unchecked.svg | 6 - app/images/icons/reddit.svg | 225 ---------------- app/images/icons/share.svg | 6 - app/images/icons/shield.svg | 6 - app/images/icons/shrink.svg | 9 - app/images/icons/shrink2.svg | 6 - app/images/icons/shuffle.svg | 6 - app/images/icons/sort-alpha-asc.svg | 8 - app/images/icons/sort-alpha-desc.svg | 8 - app/images/icons/sort-amount-asc.svg | 10 - app/images/icons/sort-amount-desc.svg | 10 - app/images/icons/sort-numberic-desc.svg | 8 - app/images/icons/sort-numeric-asc.svg | 8 - app/images/icons/sphere.svg | 6 - app/images/icons/stats-bars2.svg | 6 - app/images/icons/stats-dots.svg | 6 - app/images/icons/table.svg | 6 - app/images/icons/table2.svg | 6 - app/images/icons/target.svg | 6 - app/images/icons/tree.svg | 6 - app/images/icons/wrench.svg | 6 - app/index.html | 3 +- app/js/app.js | 12 +- app/js/config.js | 28 +- app/js/controllers/controller-comparison.js | 255 ++++++++++++++---- app/js/controllers/controller-error.js | 7 +- app/js/controllers/controller-export.js | 19 +- app/js/controllers/controller-import.js | 29 +- app/js/controllers/controller-link.js | 16 ++ app/js/controllers/controller-modal.js | 4 +- app/js/controllers/controller-outfit.js | 47 ++-- app/js/controllers/controller-shipyard.js | 1 - app/js/directives/directive-area-chart.js | 123 +++++++++ app/js/directives/directive-bar-chart.js | 97 ++++--- .../directives/directive-comparison-table.js | 80 ++++++ .../directives/directive-component-select.js | 24 +- app/js/directives/directive-header.js | 14 +- app/js/factory-utils.js | 61 +++++ app/js/service-persist.js | 72 ++++- app/js/service-serializer.js | 21 ++ app/js/shipyard/factory-component-set.js | 4 +- app/js/shipyard/factory-ship.js | 19 +- app/js/shipyard/module-shipyard.js | 32 +-- app/js/shipyard/service-components.js | 2 +- app/less/app.less | 20 +- app/less/buttons.less | 7 +- app/less/charts.less | 14 +- app/less/colors.less | 5 + app/less/comparison.less | 105 +++++++- app/less/header.less | 36 +-- app/less/icons.less | 13 +- app/less/list.less | 2 - app/less/modal.less | 10 +- app/less/outfit.less | 19 +- app/less/shipyard.less | 4 - app/less/slot.less | 1 + app/less/sortable.less | 30 +++ app/less/table.less | 11 +- app/less/utilities.less | 2 +- app/views/_header.html | 20 +- app/views/_slot-internal.html | 5 +- app/views/modal-export.html | 4 +- app/views/modal-import.html | 6 +- app/views/modal-link.html | 9 + app/views/page-comparison.html | 89 ++++-- app/views/page-error.html | 6 +- app/views/page-outfit.html | 32 ++- bower.json | 12 +- gulpfile.js | 13 +- package.json | 2 +- 146 files changed, 1096 insertions(+), 1062 deletions(-) rename app/{images => }/icons/bin.svg (100%) rename app/{images => }/icons/cancel-circle.svg (100%) rename app/{images => }/icons/checkmark.svg (100%) rename app/{images => }/icons/checkmark2.svg (100%) rename app/{images => }/icons/cogs.svg (100%) rename app/{images => }/icons/coriolis.svg (100%) rename app/{images => }/icons/download.svg (100%) rename app/{images/icons/arrow-down-left.svg => icons/embed.svg} (76%) rename app/{images => }/icons/floppy-disk.svg (100%) rename app/{images => }/icons/github-mark.svg (100%) rename app/{images => }/icons/hammer.svg (100%) rename app/{images => }/icons/info.svg (100%) rename app/{images => }/icons/link.svg (100%) rename app/{images/icons/mount-f.svg => icons/mount-F.svg} (100%) rename app/{images/icons/mount-g.svg => icons/mount-G.svg} (100%) rename app/{images/icons/mount-t.svg => icons/mount-T.svg} (100%) rename app/{images => }/icons/notification.svg (100%) rename app/{images => }/icons/question.svg (100%) rename app/{images => }/icons/rocket.svg (100%) rename app/{images => }/icons/spinner11.svg (100%) rename app/{images => }/icons/stats-bars.svg (100%) rename app/{images => }/icons/switch.svg (100%) rename app/{images => }/icons/upload.svg (100%) rename app/{images => }/icons/warning.svg (100%) delete mode 100755 app/images/icons/arrow-down-left2.svg delete mode 100755 app/images/icons/arrow-down-right.svg delete mode 100755 app/images/icons/arrow-down-right2.svg delete mode 100755 app/images/icons/arrow-down.svg delete mode 100755 app/images/icons/arrow-down2.svg delete mode 100755 app/images/icons/arrow-left.svg delete mode 100755 app/images/icons/arrow-left2.svg delete mode 100755 app/images/icons/arrow-right.svg delete mode 100755 app/images/icons/arrow-right2.svg delete mode 100755 app/images/icons/arrow-up-left.svg delete mode 100755 app/images/icons/arrow-up-left2.svg delete mode 100755 app/images/icons/arrow-up-right.svg delete mode 100755 app/images/icons/arrow-up-right2.svg delete mode 100755 app/images/icons/arrow-up.svg delete mode 100755 app/images/icons/arrow-up2.svg delete mode 100755 app/images/icons/blocked.svg delete mode 100755 app/images/icons/checkbox-checked.svg delete mode 100755 app/images/icons/checkbox-unchecked.svg delete mode 100755 app/images/icons/circle-down.svg delete mode 100755 app/images/icons/circle-left.svg delete mode 100755 app/images/icons/circle-right.svg delete mode 100755 app/images/icons/circle-up.svg delete mode 100755 app/images/icons/clipboard.svg delete mode 100755 app/images/icons/cloud-check.svg delete mode 100755 app/images/icons/cloud-download.svg delete mode 100755 app/images/icons/cloud-upload.svg delete mode 100755 app/images/icons/cloud.svg delete mode 100755 app/images/icons/cog.svg delete mode 100755 app/images/icons/coin-dollar.svg delete mode 100755 app/images/icons/cross.svg delete mode 100755 app/images/icons/enlarge.svg delete mode 100755 app/images/icons/enlarge2.svg delete mode 100755 app/images/icons/equalizer.svg delete mode 100755 app/images/icons/equalizer2.svg delete mode 100755 app/images/icons/infinite.svg delete mode 100755 app/images/icons/loop.svg delete mode 100755 app/images/icons/loop2.svg delete mode 100755 app/images/icons/menu.svg delete mode 100755 app/images/icons/menu2.svg delete mode 100755 app/images/icons/menu3.svg delete mode 100755 app/images/icons/menu4.svg delete mode 100755 app/images/icons/meter.svg delete mode 100755 app/images/icons/meter2.svg delete mode 100755 app/images/icons/minus.svg delete mode 100755 app/images/icons/move-down.svg delete mode 100755 app/images/icons/move-up.svg delete mode 100755 app/images/icons/pie-chart.svg delete mode 100755 app/images/icons/plus.svg delete mode 100755 app/images/icons/power-cord.svg delete mode 100755 app/images/icons/power.svg delete mode 100755 app/images/icons/radio-checked.svg delete mode 100755 app/images/icons/radio-checked2.svg delete mode 100755 app/images/icons/radio-unchecked.svg delete mode 100644 app/images/icons/reddit.svg delete mode 100755 app/images/icons/share.svg delete mode 100755 app/images/icons/shield.svg delete mode 100755 app/images/icons/shrink.svg delete mode 100755 app/images/icons/shrink2.svg delete mode 100755 app/images/icons/shuffle.svg delete mode 100755 app/images/icons/sort-alpha-asc.svg delete mode 100755 app/images/icons/sort-alpha-desc.svg delete mode 100755 app/images/icons/sort-amount-asc.svg delete mode 100755 app/images/icons/sort-amount-desc.svg delete mode 100755 app/images/icons/sort-numberic-desc.svg delete mode 100755 app/images/icons/sort-numeric-asc.svg delete mode 100755 app/images/icons/sphere.svg delete mode 100755 app/images/icons/stats-bars2.svg delete mode 100755 app/images/icons/stats-dots.svg delete mode 100755 app/images/icons/table.svg delete mode 100755 app/images/icons/table2.svg delete mode 100755 app/images/icons/target.svg delete mode 100755 app/images/icons/tree.svg delete mode 100755 app/images/icons/wrench.svg create mode 100644 app/js/controllers/controller-link.js create mode 100644 app/js/directives/directive-area-chart.js create mode 100644 app/js/directives/directive-comparison-table.js create mode 100644 app/js/factory-utils.js create mode 100644 app/less/sortable.less create mode 100644 app/views/modal-link.html diff --git a/app/images/icons/bin.svg b/app/icons/bin.svg similarity index 100% rename from app/images/icons/bin.svg rename to app/icons/bin.svg diff --git a/app/images/icons/cancel-circle.svg b/app/icons/cancel-circle.svg similarity index 100% rename from app/images/icons/cancel-circle.svg rename to app/icons/cancel-circle.svg diff --git a/app/images/icons/checkmark.svg b/app/icons/checkmark.svg similarity index 100% rename from app/images/icons/checkmark.svg rename to app/icons/checkmark.svg diff --git a/app/images/icons/checkmark2.svg b/app/icons/checkmark2.svg similarity index 100% rename from app/images/icons/checkmark2.svg rename to app/icons/checkmark2.svg diff --git a/app/images/icons/cogs.svg b/app/icons/cogs.svg similarity index 100% rename from app/images/icons/cogs.svg rename to app/icons/cogs.svg diff --git a/app/images/icons/coriolis.svg b/app/icons/coriolis.svg similarity index 100% rename from app/images/icons/coriolis.svg rename to app/icons/coriolis.svg diff --git a/app/images/icons/download.svg b/app/icons/download.svg similarity index 100% rename from app/images/icons/download.svg rename to app/icons/download.svg diff --git a/app/images/icons/arrow-down-left.svg b/app/icons/embed.svg similarity index 76% rename from app/images/icons/arrow-down-left.svg rename to app/icons/embed.svg index 7f4f2926..99b09ed9 100755 --- a/app/images/icons/arrow-down-left.svg +++ b/app/icons/embed.svg @@ -2,5 +2,6 @@ - + + diff --git a/app/images/icons/floppy-disk.svg b/app/icons/floppy-disk.svg similarity index 100% rename from app/images/icons/floppy-disk.svg rename to app/icons/floppy-disk.svg diff --git a/app/images/icons/github-mark.svg b/app/icons/github-mark.svg similarity index 100% rename from app/images/icons/github-mark.svg rename to app/icons/github-mark.svg diff --git a/app/images/icons/hammer.svg b/app/icons/hammer.svg similarity index 100% rename from app/images/icons/hammer.svg rename to app/icons/hammer.svg diff --git a/app/images/icons/info.svg b/app/icons/info.svg similarity index 100% rename from app/images/icons/info.svg rename to app/icons/info.svg diff --git a/app/images/icons/link.svg b/app/icons/link.svg similarity index 100% rename from app/images/icons/link.svg rename to app/icons/link.svg diff --git a/app/images/icons/mount-f.svg b/app/icons/mount-F.svg similarity index 100% rename from app/images/icons/mount-f.svg rename to app/icons/mount-F.svg diff --git a/app/images/icons/mount-g.svg b/app/icons/mount-G.svg similarity index 100% rename from app/images/icons/mount-g.svg rename to app/icons/mount-G.svg diff --git a/app/images/icons/mount-t.svg b/app/icons/mount-T.svg similarity index 100% rename from app/images/icons/mount-t.svg rename to app/icons/mount-T.svg diff --git a/app/images/icons/notification.svg b/app/icons/notification.svg similarity index 100% rename from app/images/icons/notification.svg rename to app/icons/notification.svg diff --git a/app/images/icons/question.svg b/app/icons/question.svg similarity index 100% rename from app/images/icons/question.svg rename to app/icons/question.svg diff --git a/app/images/icons/rocket.svg b/app/icons/rocket.svg similarity index 100% rename from app/images/icons/rocket.svg rename to app/icons/rocket.svg diff --git a/app/images/icons/spinner11.svg b/app/icons/spinner11.svg similarity index 100% rename from app/images/icons/spinner11.svg rename to app/icons/spinner11.svg diff --git a/app/images/icons/stats-bars.svg b/app/icons/stats-bars.svg similarity index 100% rename from app/images/icons/stats-bars.svg rename to app/icons/stats-bars.svg diff --git a/app/images/icons/switch.svg b/app/icons/switch.svg similarity index 100% rename from app/images/icons/switch.svg rename to app/icons/switch.svg diff --git a/app/images/icons/upload.svg b/app/icons/upload.svg similarity index 100% rename from app/images/icons/upload.svg rename to app/icons/upload.svg diff --git a/app/images/icons/warning.svg b/app/icons/warning.svg similarity index 100% rename from app/images/icons/warning.svg rename to app/icons/warning.svg diff --git a/app/images/icons/arrow-down-left2.svg b/app/images/icons/arrow-down-left2.svg deleted file mode 100755 index 516792b3..00000000 --- a/app/images/icons/arrow-down-left2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-down-right.svg b/app/images/icons/arrow-down-right.svg deleted file mode 100755 index dd8353a0..00000000 --- a/app/images/icons/arrow-down-right.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-down-right2.svg b/app/images/icons/arrow-down-right2.svg deleted file mode 100755 index 214a063a..00000000 --- a/app/images/icons/arrow-down-right2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-down.svg b/app/images/icons/arrow-down.svg deleted file mode 100755 index fafdb81c..00000000 --- a/app/images/icons/arrow-down.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-down2.svg b/app/images/icons/arrow-down2.svg deleted file mode 100755 index c6f26a16..00000000 --- a/app/images/icons/arrow-down2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-left.svg b/app/images/icons/arrow-left.svg deleted file mode 100755 index 6eddf01a..00000000 --- a/app/images/icons/arrow-left.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-left2.svg b/app/images/icons/arrow-left2.svg deleted file mode 100755 index b07eea54..00000000 --- a/app/images/icons/arrow-left2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-right.svg b/app/images/icons/arrow-right.svg deleted file mode 100755 index c95cbdf4..00000000 --- a/app/images/icons/arrow-right.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-right2.svg b/app/images/icons/arrow-right2.svg deleted file mode 100755 index c69ae923..00000000 --- a/app/images/icons/arrow-right2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-up-left.svg b/app/images/icons/arrow-up-left.svg deleted file mode 100755 index 9fb3ec5b..00000000 --- a/app/images/icons/arrow-up-left.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-up-left2.svg b/app/images/icons/arrow-up-left2.svg deleted file mode 100755 index 0697ef97..00000000 --- a/app/images/icons/arrow-up-left2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-up-right.svg b/app/images/icons/arrow-up-right.svg deleted file mode 100755 index 07fa395e..00000000 --- a/app/images/icons/arrow-up-right.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-up-right2.svg b/app/images/icons/arrow-up-right2.svg deleted file mode 100755 index e1d63292..00000000 --- a/app/images/icons/arrow-up-right2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-up.svg b/app/images/icons/arrow-up.svg deleted file mode 100755 index 2d6e8640..00000000 --- a/app/images/icons/arrow-up.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/arrow-up2.svg b/app/images/icons/arrow-up2.svg deleted file mode 100755 index 106cd648..00000000 --- a/app/images/icons/arrow-up2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/blocked.svg b/app/images/icons/blocked.svg deleted file mode 100755 index b5f0b4ac..00000000 --- a/app/images/icons/blocked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/checkbox-checked.svg b/app/images/icons/checkbox-checked.svg deleted file mode 100755 index af03c18f..00000000 --- a/app/images/icons/checkbox-checked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/checkbox-unchecked.svg b/app/images/icons/checkbox-unchecked.svg deleted file mode 100755 index 2168d9ee..00000000 --- a/app/images/icons/checkbox-unchecked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/circle-down.svg b/app/images/icons/circle-down.svg deleted file mode 100755 index 9652b85f..00000000 --- a/app/images/icons/circle-down.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/circle-left.svg b/app/images/icons/circle-left.svg deleted file mode 100755 index 2fac6fbe..00000000 --- a/app/images/icons/circle-left.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/circle-right.svg b/app/images/icons/circle-right.svg deleted file mode 100755 index 3ae9f1db..00000000 --- a/app/images/icons/circle-right.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/circle-up.svg b/app/images/icons/circle-up.svg deleted file mode 100755 index 2798916b..00000000 --- a/app/images/icons/circle-up.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/clipboard.svg b/app/images/icons/clipboard.svg deleted file mode 100755 index cd6d7384..00000000 --- a/app/images/icons/clipboard.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/cloud-check.svg b/app/images/icons/cloud-check.svg deleted file mode 100755 index 1e21a0fd..00000000 --- a/app/images/icons/cloud-check.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/cloud-download.svg b/app/images/icons/cloud-download.svg deleted file mode 100755 index bcaeba24..00000000 --- a/app/images/icons/cloud-download.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/cloud-upload.svg b/app/images/icons/cloud-upload.svg deleted file mode 100755 index c2fd0f9d..00000000 --- a/app/images/icons/cloud-upload.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/cloud.svg b/app/images/icons/cloud.svg deleted file mode 100755 index 33e42cb1..00000000 --- a/app/images/icons/cloud.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/cog.svg b/app/images/icons/cog.svg deleted file mode 100755 index 4b8fcbc0..00000000 --- a/app/images/icons/cog.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/coin-dollar.svg b/app/images/icons/coin-dollar.svg deleted file mode 100755 index 3b159e58..00000000 --- a/app/images/icons/coin-dollar.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/cross.svg b/app/images/icons/cross.svg deleted file mode 100755 index 601c1582..00000000 --- a/app/images/icons/cross.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/enlarge.svg b/app/images/icons/enlarge.svg deleted file mode 100755 index ab9a5a23..00000000 --- a/app/images/icons/enlarge.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/app/images/icons/enlarge2.svg b/app/images/icons/enlarge2.svg deleted file mode 100755 index f25f27bb..00000000 --- a/app/images/icons/enlarge2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/equalizer.svg b/app/images/icons/equalizer.svg deleted file mode 100755 index 73db4cbf..00000000 --- a/app/images/icons/equalizer.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/equalizer2.svg b/app/images/icons/equalizer2.svg deleted file mode 100755 index d1a55665..00000000 --- a/app/images/icons/equalizer2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/infinite.svg b/app/images/icons/infinite.svg deleted file mode 100755 index b37c52f2..00000000 --- a/app/images/icons/infinite.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/loop.svg b/app/images/icons/loop.svg deleted file mode 100755 index d60df53c..00000000 --- a/app/images/icons/loop.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/loop2.svg b/app/images/icons/loop2.svg deleted file mode 100755 index 25f330c0..00000000 --- a/app/images/icons/loop2.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/menu.svg b/app/images/icons/menu.svg deleted file mode 100755 index 0a5bf2db..00000000 --- a/app/images/icons/menu.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/menu2.svg b/app/images/icons/menu2.svg deleted file mode 100755 index a251d0f9..00000000 --- a/app/images/icons/menu2.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/app/images/icons/menu3.svg b/app/images/icons/menu3.svg deleted file mode 100755 index 3ac19f6e..00000000 --- a/app/images/icons/menu3.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/menu4.svg b/app/images/icons/menu4.svg deleted file mode 100755 index 5b5ca2e4..00000000 --- a/app/images/icons/menu4.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/meter.svg b/app/images/icons/meter.svg deleted file mode 100755 index a71d3352..00000000 --- a/app/images/icons/meter.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/meter2.svg b/app/images/icons/meter2.svg deleted file mode 100755 index f4536a52..00000000 --- a/app/images/icons/meter2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/minus.svg b/app/images/icons/minus.svg deleted file mode 100755 index e0aec824..00000000 --- a/app/images/icons/minus.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/move-down.svg b/app/images/icons/move-down.svg deleted file mode 100755 index 645017be..00000000 --- a/app/images/icons/move-down.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/images/icons/move-up.svg b/app/images/icons/move-up.svg deleted file mode 100755 index 5823d110..00000000 --- a/app/images/icons/move-up.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/images/icons/pie-chart.svg b/app/images/icons/pie-chart.svg deleted file mode 100755 index 85bea4ca..00000000 --- a/app/images/icons/pie-chart.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/plus.svg b/app/images/icons/plus.svg deleted file mode 100755 index e0cee422..00000000 --- a/app/images/icons/plus.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/power-cord.svg b/app/images/icons/power-cord.svg deleted file mode 100755 index d9c8da6f..00000000 --- a/app/images/icons/power-cord.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/app/images/icons/power.svg b/app/images/icons/power.svg deleted file mode 100755 index 234d3097..00000000 --- a/app/images/icons/power.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/radio-checked.svg b/app/images/icons/radio-checked.svg deleted file mode 100755 index c20ef3f8..00000000 --- a/app/images/icons/radio-checked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/radio-checked2.svg b/app/images/icons/radio-checked2.svg deleted file mode 100755 index 5fae3bac..00000000 --- a/app/images/icons/radio-checked2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/radio-unchecked.svg b/app/images/icons/radio-unchecked.svg deleted file mode 100755 index 87d5defe..00000000 --- a/app/images/icons/radio-unchecked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/reddit.svg b/app/images/icons/reddit.svg deleted file mode 100644 index ae97cd78..00000000 --- a/app/images/icons/reddit.svg +++ /dev/null @@ -1,225 +0,0 @@ - - - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/images/icons/share.svg b/app/images/icons/share.svg deleted file mode 100755 index 5abb7bdf..00000000 --- a/app/images/icons/share.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/shield.svg b/app/images/icons/shield.svg deleted file mode 100755 index 324a72b7..00000000 --- a/app/images/icons/shield.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/shrink.svg b/app/images/icons/shrink.svg deleted file mode 100755 index bdd7f454..00000000 --- a/app/images/icons/shrink.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/app/images/icons/shrink2.svg b/app/images/icons/shrink2.svg deleted file mode 100755 index abcad484..00000000 --- a/app/images/icons/shrink2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/shuffle.svg b/app/images/icons/shuffle.svg deleted file mode 100755 index d77fc75b..00000000 --- a/app/images/icons/shuffle.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/sort-alpha-asc.svg b/app/images/icons/sort-alpha-asc.svg deleted file mode 100755 index c7274dcd..00000000 --- a/app/images/icons/sort-alpha-asc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/app/images/icons/sort-alpha-desc.svg b/app/images/icons/sort-alpha-desc.svg deleted file mode 100755 index 0851d6e1..00000000 --- a/app/images/icons/sort-alpha-desc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/app/images/icons/sort-amount-asc.svg b/app/images/icons/sort-amount-asc.svg deleted file mode 100755 index bcd9e967..00000000 --- a/app/images/icons/sort-amount-asc.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/app/images/icons/sort-amount-desc.svg b/app/images/icons/sort-amount-desc.svg deleted file mode 100755 index 4fa65a92..00000000 --- a/app/images/icons/sort-amount-desc.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/app/images/icons/sort-numberic-desc.svg b/app/images/icons/sort-numberic-desc.svg deleted file mode 100755 index a8d8594b..00000000 --- a/app/images/icons/sort-numberic-desc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/app/images/icons/sort-numeric-asc.svg b/app/images/icons/sort-numeric-asc.svg deleted file mode 100755 index b7831aee..00000000 --- a/app/images/icons/sort-numeric-asc.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/app/images/icons/sphere.svg b/app/images/icons/sphere.svg deleted file mode 100755 index 63e52897..00000000 --- a/app/images/icons/sphere.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/stats-bars2.svg b/app/images/icons/stats-bars2.svg deleted file mode 100755 index 9747e177..00000000 --- a/app/images/icons/stats-bars2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/stats-dots.svg b/app/images/icons/stats-dots.svg deleted file mode 100755 index ecbc953e..00000000 --- a/app/images/icons/stats-dots.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/table.svg b/app/images/icons/table.svg deleted file mode 100755 index 0322acb8..00000000 --- a/app/images/icons/table.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/table2.svg b/app/images/icons/table2.svg deleted file mode 100755 index 46dd152c..00000000 --- a/app/images/icons/table2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/target.svg b/app/images/icons/target.svg deleted file mode 100755 index b78367c2..00000000 --- a/app/images/icons/target.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/tree.svg b/app/images/icons/tree.svg deleted file mode 100755 index 03537e06..00000000 --- a/app/images/icons/tree.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/images/icons/wrench.svg b/app/images/icons/wrench.svg deleted file mode 100755 index 825b395f..00000000 --- a/app/images/icons/wrench.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/index.html b/app/index.html index 6802d6ee..7ba78ce8 100644 --- a/app/index.html +++ b/app/index.html @@ -21,7 +21,7 @@ - +
<%= svgContent %>
@@ -47,6 +47,7 @@ })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '<%= uaTracking %> ', 'auto'); + var GAPI_KEY = '<%= gapiKey %>'; <% } %> diff --git a/app/js/app.js b/app/js/app.js index 2a3712ce..931ca90b 100644 --- a/app/js/app.js +++ b/app/js/app.js @@ -1,4 +1,4 @@ -angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'shipyard', 'ngLodash', 'app.templates']) +angular.module('app', ['ngTouch', 'ui.router', 'ct.ui.router.extras.sticky', 'ui.sortable', 'shipyard', 'ngLodash', 'app.templates']) .run(['$rootScope', '$location', '$window', '$document','$state','commonArray','shipPurpose','shipSize','hardPointClass','internalGroupMap','hardpointsGroupMap', function ($rootScope, $location, $window, $doc, $state, CArr, shipPurpose, sz, hpc, igMap, hgMap) { // Redirect any state transition errors to the error controller/state $rootScope.$on('$stateChangeError', function(e, toState, toParams, fromState, fromParams, error){ @@ -9,8 +9,8 @@ angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'shipyard', 'n // Track on Google analytics if available $rootScope.$on('$stateChangeSuccess', function(e, to, toParams, from, fromParams) { $rootScope.prevState = { name: from.name, params: fromParams }; - if(to.url) { // Only track states that have a URL - if ($window.ga) ga('send', 'pageview', {page: $location.path()}); + if(to.url && $window.ga) { // Only track states that have a URL + ga('send', 'pageview', {page: $location.path()}); } }); @@ -26,8 +26,8 @@ angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'shipyard', 'n // Formatters $rootScope.fCrd = d3.format(',.0f'); $rootScope.fPwr = d3.format(',.2f'); - $rootScope.fRound = function(d) { return d3.round(d, 2) }; - $rootScope.fRound4 = function(d) { return d3.round(d, 4) }; + $rootScope.fRound = function(d) { return d3.round(d, 2); }; + $rootScope.fRound4 = function(d) { return d3.round(d, 4); }; $rootScope.fPct = d3.format('.2%'); $rootScope.fRPct = d3.format('%'); $rootScope.fTime = function(d) { return Math.floor(d/60) + ":" + ("00" + (d%60)).substr(-2,2); }; @@ -44,6 +44,6 @@ angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'shipyard', 'n $rootScope.bgClicked = function (e) { $rootScope.$broadcast('close', e); - } + }; }]); diff --git a/app/js/config.js b/app/js/config.js index b3bd79fa..6da41298 100644 --- a/app/js/config.js +++ b/app/js/config.js @@ -11,9 +11,8 @@ angular.module('app').config(['$provide','$stateProvider', '$urlRouterProvider', .state('outfit', { url: '/outfit/:shipId/:code?bn', params: { - // TODO: Squash:false not working due to UI-router issue - shipId: { value: 'sidewinder', squash: false}, // Allow 'shipId' parameter to default to - code: { value: null, squash: true } // Allow 'code' parameter to be empty/optional + shipId: { value: 'sidewinder', squash: false}, // Allow 'shipId' parameter to default to sidewinder + code: { value: null, squash: true } // Allow 'code' parameter to be empty/optional }, templateUrl: 'views/page-outfit.html', controller: 'OutfitController', @@ -26,20 +25,35 @@ angular.module('app').config(['$provide','$stateProvider', '$urlRouterProvider', }, sticky: true }) + .state('compare', { + url: '/compare/:name', + params: { + name: {value: null, squash: true } + }, + templateUrl: 'views/page-comparison.html', + controller: 'ComparisonController', + sticky: true + }) + .state('comparison', { + url: '/comparison/:code', + templateUrl: 'views/page-comparison.html', + controller: 'ComparisonController', + sticky: true + }) .state('shipyard', { url: '/', templateUrl: 'views/page-shipyard.html', controller: 'ShipyardController', sticky: true }) - .state('comparison', { url: '/comparison', templateUrl: 'views/page-comparison.html', controller: 'ComparisonController', sticky: true }) .state('error', { params: {type:null, message:null, details: null }, templateUrl: 'views/page-error.html', controller: 'ErrorController', sticky: true }) // Modal States and views .state('modal', { abstract: true, views:{ "modal": { templateUrl: "views/_modal.html", controller: 'ModalController' } } }) .state('modal.about', { views: { "modal-content": { templateUrl: "views/modal-about.html" } } }) - .state('modal.export', { views: { "modal-content": { templateUrl: "views/modal-export.html", controller: 'ExportController' } } }) - .state('modal.import', { views: { "modal-content": { templateUrl: "views/modal-import.html", controller: 'ImportController' } } }) + .state('modal.export', { params: {title:null, data: null, promise: null}, views: { "modal-content": { templateUrl: "views/modal-export.html", controller: 'ExportController' } } }) + .state('modal.import', { params: {obj:null}, views: { "modal-content": { templateUrl: "views/modal-import.html", controller: 'ImportController' } } }) + .state('modal.link', { params: {url:null}, views: { "modal-content": { templateUrl: "views/modal-link.html", controller: 'LinkController' } } }) .state('modal.delete', { views: { "modal-content": { templateUrl: "views/modal-delete.html", controller: 'DeleteController' } } }); // Redirects - $urlRouterProvider.when('/outfit','/outfit/sidewinder/'); + $urlRouterProvider.when('/outfit','/outfit/sidewinder'); /** * 404 Handler - Keep current URL/ do not redirect, change to error state. diff --git a/app/js/controllers/controller-comparison.js b/app/js/controllers/controller-comparison.js index 0db65cde..0af6c581 100644 --- a/app/js/controllers/controller-comparison.js +++ b/app/js/controllers/controller-comparison.js @@ -1,66 +1,211 @@ -angular.module('app').controller('ComparisonController', ['$rootScope', '$filter', '$scope', 'ShipFacets', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function ($rootScope, $filter, $scope, ShipFacets, Ships, Ship, Persist, Serializer) { - $rootScope.title = 'Coriolis - Comparison'; - $rootScope.bodyClass = null; - $scope.facets = ShipFacets; - $scope.subFacets = []; - - for (var i = 0, l = $scope.facets.length; i < l; i++) { - var facet = $scope.facets[i]; - if(facet.prop) { - $scope.subFacets.push({ - prop: facet.prop, - fmt: $rootScope[facet.fmt], - unit: facet.unit - }); - } else { - for (var j = 0, pl = facet.props.length; j < pl; j++) { - $scope.subFacets.push({ - sub: true, - start: j == 0, - prop: facet.props[j], - label: facet.lbls[j], - fmt: $rootScope[facet.fmt], - unit: facet.unit - }); - } - } - } - - var comparison = $scope.comparison = []; - var orderBy = $filter('orderBy'); - var buildCount = 0; - - for (var shipId in Persist.builds) { - var data = Ships[shipId]; - for (var buildName in Persist.builds[shipId]) { - var code = Persist.builds[shipId][buildName]; - var b = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance - Serializer.toShip(b, code); // Populate components from 'code' URL param - // Extend ship instance and add properties below - b.buildName = buildName; - b.code = code; - b.pctRetracted = b.powerRetracted / b.powerAvailable; - b.pctDeployed = b.powerDeployed / b.powerAvailable; - comparison.push(b); // Add ship build to comparison - } - } - - $scope.chartHeight = 45 + (25 * comparison.length); - $scope.predicate = 'ship.name'; +angular.module('app').controller('ComparisonController', ['lodash', '$rootScope', '$filter', '$scope', '$state', '$stateParams', 'Utils', 'ShipFacets', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function (_, $rootScope, $filter, $scope, $state, $stateParams, Utils, ShipFacets, Ships, Ship, Persist, Serializer) { + $rootScope.title = 'Coriolis - Compare'; + $scope.predicate = 'ship.name'; // Sort by ship name as default $scope.desc = true; + $scope.facetSortOpts = { containment: '#facet-container', orderChanged: function () { $scope.saved = false; } }; + $scope.builds = []; + $scope.unusedBuilds = []; + $scope.name = $stateParams.name; + $scope.compareMode = !$stateParams.code; + $scope.importObj = {}; // Used for importing comparison builds (from permalinked comparison) + var defaultFacets = [9,6,4,1,3,2]; // Reverse order of Armour, Shields, Speed, Jump Range, Cargo Capacity, Cost + var facets = $scope.facets = angular.copy(ShipFacets); - $scope.sortProperty = function (e) { - var prop = angular.element(e.target).attr('prop'); // Get component ID - if(prop) { - $scope.sort(prop); + /** + * Add an existing build to the comparison. The build must be saved locally. + * @param {string} shipId The unique ship key/id + * @param {string} buildName The build name + */ + $scope.addBuild = function (shipId, buildName, code) { + var data = Ships[shipId]; // Get ship properties + var code = code? code : Persist.builds[shipId][buildName]; // Retrieve build code if not passed + var b = new Ship(shipId, data.properties, data.slots); // Create a new Ship instance + Serializer.toShip(b, code); // Populate components from code + // Extend ship instance and add properties below + b.buildName = buildName; + b.code = code; + b.pctRetracted = b.powerRetracted / b.powerAvailable; + b.pctDeployed = b.powerDeployed / b.powerAvailable; + $scope.builds.push(b); // Add ship build to comparison + $scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc); // Resort + _.remove($scope.unusedBuilds, function (b) { // Remove from unused builds + return b.id == shipId && b.buildName == buildName; + }); + $scope.saved = false; + }; + + /** + * Removes a build from the comparison + * @param {string} shipId The unique ship key/id + * @param {string} buildName The build name + */ + $scope.removeBuild = function (shipId, buildName) { + _.remove($scope.builds, function (b) { + if (b.id == shipId && b.buildName == buildName) { + $scope.unusedBuilds.push({id: shipId, buildName: buildName, name: b.name}); // Add build back to unused builds + return true; + } + return false; + }); + $scope.saved = false; + }; + + /** + * Toggles the selected the set of facets used in the comparison + * @param {number} i The index of the facet in facets + */ + $scope.toggleFacet = function (i) { + facets[i].active = !facets[i].active; + $scope.tblUpdate = !$scope.tblUpdate; // Simple switch to trigger the table to update + $scope.saved = false; + }; + + /** + * Click handler for sorting by facets in the table + * @param {object} e Event object + */ + $scope.handleClick = function (e) { + var elem = angular.element(e.target); + if(elem.attr('prop')) { // Get component ID + $scope.sort(elem.attr('prop')); + } + else if (elem.attr('del')) { // Delete index + $scope.removeBuild(elem.attr('del')); } }; + /** + * Sort the comparison array based on the selected facet / ship property + * @param {string} key Ship property + */ $scope.sort = function (key) { $scope.desc = ($scope.predicate == key)? !$scope.desc : $scope.desc; $scope.predicate = key; - $scope.comparison = orderBy($scope.comparison, $scope.predicate, $scope.desc); + $scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc); }; - $scope.sort('name'); + /** + * Saves the current comparison's selected facets and builds + */ + $scope.save = function() { + $scope.name = $scope.name.trim(); + if ($scope.name == 'all') { + return; + } + var selectedFacets = []; + facets.forEach(function(f) { + if(f.active) { + selectedFacets.unshift(f.index); + } + }); + Persist.saveComparison($scope.name, $scope.builds, selectedFacets); + $state.go('compare', {name: $scope.name}, {location:'replace', reload:false}); + $scope.saved = true; + }; + + /** + * Permantently delete the current comparison + */ + $scope.delete = function() { + Persist.deleteComparison($scope.name); + $state.go('compare', {name: null}, {location:'replace', reload:true}); + }; + + $scope.nameChange = function() { + $scope.saved = false; + }; + + $scope.selectBuilds = function(s, e) { + e.stopPropagation(); + $scope.showBuilds = s; + }; + + $scope.permalink = function(e) { + e.stopPropagation(); + $state.go('modal.link', {url: genPermalink()}); + }; + + $scope.embed = function(e) { + e.stopPropagation(); + var promise = Utils.shortenUrl( genPermalink()).then( + function (shortUrl) { + return Utils.comparisonBBCode(facets, $scope.builds, shortUrl); + }, + function (e) { + return 'Error - ' + e.statusText; + } + ); + $state.go('modal.export', {promise: promise, title:'Forum BBCode'}); + }; + + function genPermalink() { + var selectedFacets = []; + facets.forEach(function(f) { + if(f.active) { + selectedFacets.unshift(f.index); + } + }); + var code = Serializer.fromComparison( + $scope.name, + $scope.builds, + selectedFacets, + $scope.predicate, + $scope.desc + ); + return $state.href('comparison', {code: code}, {absolute:true}); + }; + + /* Event listeners */ + $scope.$on('close', function() { + $scope.showBuilds = false; + }); + + /* Initialization */ + if ($scope.compareMode) { + if ($scope.name == 'all') { + for (var shipId in Persist.builds) { + for (var buildName in Persist.builds[shipId]) { + $scope.addBuild(shipId, buildName); + } + } + } else { + for (var shipId in Persist.builds) { + for (var buildName in Persist.builds[shipId]) { + $scope.unusedBuilds.push({id: shipId, buildName: buildName, name: Ships[shipId].properties.name}); + } + } + var comparisonData = Persist.getComparison($scope.name); + if (comparisonData) { + defaultFacets = comparisonData.facets; + comparisonData.builds.forEach(function (b) { + $scope.addBuild(b.shipId, b.buildName); + }); + $scope.saved = true; + } + } + } else { + try { + var comparisonData = Serializer.toComparison($stateParams.code); + defaultFacets = comparisonData.f; + $scope.name = comparisonData.n + $scope.predicate = comparisonData.p; + $scope.desc = comparisonData.d; + comparisonData.b.forEach(function (build) { + $scope.addBuild(build.s, build.n, build.c); + if(!$scope.importObj[build.s]) { + $scope.importObj[build.s] = {}; + } + $scope.importObj[build.s][build.n] = build.c; + }); + } catch (e) { + throw { type: 'bad-comparison', message: e.message, details: e }; + } + } + + // Replace fmt with actual format function as defined in rootScope and retain original index + facets.forEach(function(f,i) { f.fmt = $rootScope[f.fmt]; f.index = i; }); + // Remove default facets, mark as active, and add them back in selected order + _.pullAt(facets, defaultFacets).forEach(function (f) { f.active = true; facets.unshift(f); }); + + }]); \ No newline at end of file diff --git a/app/js/controllers/controller-error.js b/app/js/controllers/controller-error.js index 82801f91..409923d3 100644 --- a/app/js/controllers/controller-error.js +++ b/app/js/controllers/controller-error.js @@ -7,24 +7,23 @@ angular.module('app') switch ($scope.type) { case 404: - $rootScope.bodyClass = 'deep-space'; $scope.msgPre = 'Page'; $scope.msgHighlight = $scope.path; $scope.msgPost = 'Not Found'; break; case 'no-ship': - $rootScope.bodyClass = 'docking-bay'; + //$rootScope.bodyClass = 'docking-bay'; $scope.msgPre = 'Ship'; $scope.msgHighlight = $p.message; $scope.msgPost = 'does not exist'; break; case 'build-fail': - $rootScope.bodyClass = 'ship-explode'; // TODO: create background imag for this + //$rootScope.bodyClass = 'ship-explode'; // TODO: create background imag for this $scope.msgPre = 'Build Failure!'; $scope.details = $p.details; break; default: - $rootScope.bodyClass = 'thargoid'; // TODO: create background imag for this + //$rootScope.bodyClass = 'thargoid'; // TODO: create background imag for this $scope.msgPre = "Uh, Jameson, we have a problem.."; $scope.errorMessage = $p.message; $scope.details = $p.details; diff --git a/app/js/controllers/controller-export.js b/app/js/controllers/controller-export.js index d91954cc..dd9c44f6 100644 --- a/app/js/controllers/controller-export.js +++ b/app/js/controllers/controller-export.js @@ -1,7 +1,18 @@ -angular.module('app').controller('ExportController', ['$scope', 'Persist', function ($scope, Persist) { - $scope.builds = { - builds: Persist.builds - // TODO: add comparisons +angular.module('app').controller('ExportController', ['$scope', '$stateParams', function ($scope, $stateParams) { + + $scope.title = $stateParams.title || 'Export'; + + if ($stateParams.promise) { + $scope.export = 'Generating...'; + $stateParams.promise.then(function(data){ + $scope.export = data; + }); + } else { + $scope.export = angular.toJson($stateParams.data, true); + } + + $scope.onTextClick = function ($event) { + $event.target.select(); }; }]); \ No newline at end of file diff --git a/app/js/controllers/controller-import.js b/app/js/controllers/controller-import.js index 735179dc..62235e28 100644 --- a/app/js/controllers/controller-import.js +++ b/app/js/controllers/controller-import.js @@ -1,7 +1,9 @@ -angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function ($scope, Ships, Ship, Persist, Serializer) { +angular.module('app').controller('ImportController', ['$scope', '$stateParams', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function ($scope, $stateParams, Ships, Ship, Persist, Serializer) { $scope.jsonValid = false; $scope.importData = null; $scope.errorMsg = null; + $scope.canEdit = true; + $scope.builds = $stateParams.obj || null; $scope.validateJson = function() { var importObj = null; @@ -10,7 +12,7 @@ angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship $scope.builds = null; $scope.ships = Ships; - if(!$scope.importData) return; + if (!$scope.importData) { return; } try { importObj = angular.fromJson($scope.importData); @@ -24,15 +26,15 @@ angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship return; } - if ((!importObj.builds || !Object.keys(importObj.builds).length) && (!importObj.comparisons || !Object.keys(importObj.comparisons).length)) { - $scope.errorMsg = 'No builds or comparisons in data'; + if ((!importObj.builds || !Object.keys(importObj.builds).length)) { + $scope.errorMsg = 'No builds in data'; return; } for (var shipId in importObj.builds) { var shipData = Ships[shipId]; if (shipData) { - for (buildName in importObj.builds[shipId]) { + for (var buildName in importObj.builds[shipId]) { if (typeof importObj.builds[shipId][buildName] != 'string') { $scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" must be a string!'; return; @@ -41,7 +43,6 @@ angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship // Actually build the ship with the code to ensure it's valid Serializer.toShip(new Ship(shipId, shipData.properties, shipData.slots), importObj.builds[shipId][buildName]); } catch (e) { - console.log(e); $scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" is not valid!'; return; } @@ -53,15 +54,12 @@ angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship $scope.builds = importObj.builds; } - // Check for comparison object - // if (importObj.comparisons) - $scope.jsonValid = true; }; $scope.hasBuild = function (shipId, name) { - return Persist.getBuild(shipId, name) != null; - } + return Persist.getBuild(shipId, name) !== null; + }; $scope.process = function() { var builds = $scope.builds; @@ -75,7 +73,6 @@ angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship }; } } - $scope.processed = true; }; @@ -93,4 +90,12 @@ angular.module('app').controller('ImportController', ['$scope', 'ShipsDB', 'Ship $scope.$parent.dismiss(); }; + /* Initialization */ + + if ($scope.builds) { // If import is passed an build object + $scope.canEdit = false; + $scope.process(); + } + + }]); \ No newline at end of file diff --git a/app/js/controllers/controller-link.js b/app/js/controllers/controller-link.js new file mode 100644 index 00000000..75041907 --- /dev/null +++ b/app/js/controllers/controller-link.js @@ -0,0 +1,16 @@ +angular.module('app').controller('LinkController', ['$scope', 'Utils', '$stateParams', function ($scope, Utils, $stateParams) { + $scope.url = $stateParams.url; + $scope.shortenedUrl = 'Shortening...'; + + $scope.onTextClick = function ($event) { + $event.target.select(); + }; + + Utils.shortenUrl($scope.url) + .then(function(url) { + $scope.shortenedUrl = url; + },function(e) { + $scope.shortenedUrl = 'Error - ' + e.statusText; + }); + +}]); \ No newline at end of file diff --git a/app/js/controllers/controller-modal.js b/app/js/controllers/controller-modal.js index 614b2256..203d6155 100644 --- a/app/js/controllers/controller-modal.js +++ b/app/js/controllers/controller-modal.js @@ -1,5 +1,5 @@ angular.module('app').controller('ModalController', ['$rootScope','$scope', '$state', function ($rootScope, $scope, $state) { - var dismissListener; + $scope.dismiss = function() { if ($rootScope.prevState) { var state = $rootScope.prevState; @@ -7,7 +7,7 @@ angular.module('app').controller('ModalController', ['$rootScope','$scope', '$st } else { $state.go('shipyard'); } - } + }; $scope.$on('close', $scope.dismiss); diff --git a/app/js/controllers/controller-outfit.js b/app/js/controllers/controller-outfit.js index c71150c8..988bedc7 100644 --- a/app/js/controllers/controller-outfit.js +++ b/app/js/controllers/controller-outfit.js @@ -11,6 +11,7 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s } $scope.buildName = $p.bn; + $rootScope.title = ship.name + ($scope.buildName? ' - ' + $scope.buildName : ''); $scope.ship = ship; $scope.pp = ship.common[0]; // Power Plant $scope.th = ship.common[1]; // Thruster @@ -24,11 +25,25 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s $scope.availCS = Components.forShip(ship.id); $scope.selectedSlot = null; $scope.savedCode = Persist.getBuild(ship.id, $scope.buildName); - $rootScope.title = ship.name + ($scope.buildName? ' - ' + $scope.buildName: ''); - $rootScope.bodyClass = 'docking-bay'; - // for debugging - window.myScope = $scope; + $scope.jrSeries = { + xMin: ship.unladenMass, + xMax: ship.ladenMass, + func: ship.jumpRangeWithMass.bind(ship) + }; + $scope.jrChart = { + labels: { + xAxis: { + title:'Ship Mass', + unit: 'T' + }, + yAxis: { + title:'Jump Range', + unit: 'LY' + } + }, + watch: $scope.fsd + }; /** * 'Opens' a select for component selection. @@ -72,7 +87,7 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s $scope.code = Serializer.fromShip(ship); updateState(); } - } + }; /** * Reload the build from the last save. @@ -103,7 +118,7 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s $scope.savedCode = $scope.code; updateState(); } - } + }; /** * Permanently delete the current build and redirect/reload this controller @@ -111,13 +126,12 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s */ $scope.deleteBuild = function() { Persist.deleteBuild(ship.id, $scope.buildName); - $rootScope.$broadcast('buildDeleted', $scope.saveName, ship.id); $state.go('outfit', {shipId: ship.id, code: null, bn: null}, {location:'replace', reload:true}); - } + }; $scope.bnChange = function(){ $scope.savedCode = Persist.getBuild(ship.id, $scope.buildName); - } + }; $scope.toggleCost = function(item) { item.incCost = !item.incCost; @@ -132,24 +146,17 @@ angular.module('app').controller('OutfitController', ['$rootScope','$scope', '$s // Utilify functions function updateState() { $state.go('outfit', {shipId: ship.id, code: $scope.code, bn: $scope.buildName}, {location:'replace', notify:false}); + $scope.jrSeries.xMin = ship.unladenMass; + $scope.jrSeries.xMax = ship.ladenMass; } - // Event listeners - $scope.$on('keyup', function (e, keyEvent) { - // CTRL + S or CMD + S will override the default and save the build is possible - if (keyEvent.keycode == 83 && keyEvent.ctrlKey) { - e.preventDefault(); - $scope.saveBuild(); - } - }); - // Hide any open menu/slot/etc if escape key is pressed - $scope.$on('escape', function (e, keyEvent) { + $scope.$on('escape', function () { $scope.selectedSlot = null; $scope.$apply(); }); // Hide any open menu/slot/etc if the background is clicked - $scope.$on('close', function (e, keyEvent) { + $scope.$on('close', function () { $scope.selectedSlot = null; }); diff --git a/app/js/controllers/controller-shipyard.js b/app/js/controllers/controller-shipyard.js index ec9929f7..78751edc 100644 --- a/app/js/controllers/controller-shipyard.js +++ b/app/js/controllers/controller-shipyard.js @@ -1,5 +1,4 @@ angular.module('app').controller('ShipyardController', ['$rootScope', 'ShipsDB', function ($rootScope, ships) { $rootScope.title = 'Coriolis'; - $rootScope.bodyClass = 'docking-bay'; $rootScope.ships = ships; }]); \ No newline at end of file diff --git a/app/js/directives/directive-area-chart.js b/app/js/directives/directive-area-chart.js new file mode 100644 index 00000000..d2c3a43f --- /dev/null +++ b/app/js/directives/directive-area-chart.js @@ -0,0 +1,123 @@ +angular.module('app').directive('areaChart', function () { + + + return { + restrict: 'A', + scope:{ + config: '=', + series: '=', + height: '=', + width: '=' + }, + link: function(scope, element) { + var width = scope.width, + height = scope.height, + series = scope.series, + config = scope.config, + labels = config.labels, + margin = {top: 15, right: 15, bottom: 35, left: 50}, + w = width - margin.left - margin.right, + h = height - margin.top - margin.bottom, + fmt = d3.format('.3r'), + fmtLong = d3.format('.2f'); + + // Create chart + var svg = d3.select(element[0]).append("svg") + .attr("width", width) + .attr("height", height) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + // Define Axes + var x = d3.scale.linear().range([0, w]); + var y = d3.scale.linear().range([h, 0]); + var xAxis = d3.svg.axis().outerTickSize(0).orient("bottom").tickFormat(fmt); + var yAxis = d3.svg.axis().outerTickSize(0).orient("left").tickFormat(fmt); + // Define Area + var area = d3.svg.area().x(function(d) { return x(d[0]); }).y0(h).y1(function(d) { return y(d[1]); }); + + var gradient = svg.append("defs") + .append("linearGradient") + .attr("id", "gradient") + .attr("x1", "0%").attr("y1", "0%") + .attr("x2", "100%").attr("y2", "100%") + .attr("spreadMethod", "pad"); + gradient.append("stop") + .attr("offset", "0%") + .attr("stop-color", "#ff8c0d") + .attr("stop-opacity", 1); + gradient.append("stop") + .attr("offset", "100%") + .attr("stop-color", "#ff3b00") + .attr("stop-opacity", 1); + + // Create Y Axis SVG Elements + svg.append("g").attr("class", "y axis") + .append("text") + .attr("transform", "rotate(-90)") + .attr("y", -40) + .attr("x", -h/2) + .attr("dy", ".1em") + .style("text-anchor", "middle") + .text(labels.yAxis.title + ' (' + labels.yAxis.unit + ')'); + // Create X Axis SVG Elements + svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + h + ")") + .append("text") + .attr("y", 30) + .attr("x", w/2) + .attr("dy", ".1em") + .style("text-anchor", "middle") + .text(labels.xAxis.title + ' (' + labels.xAxis.unit + ')'); + + // Create and Add tooltip + var tip = svg.append("g").style("display", "none"); + tip.append("circle") + .attr("class", "marker") + .attr("r", 4); + tip.append("text").attr("class", 'label x').attr("y", -2); + tip.append("text").attr("class", 'label y').attr("y", '0.7em'); + + + + /** + * Watch for changes in the series data (mass changes, etc) + */ + scope.$watchCollection('series', render); + scope.$watchCollection('config.watch', render); + + function render() { + var data = []; + var func = series.func; + for (var d = series.xMin; d <= series.xMax; d++) { + data.push([ d, func(d) ]); + } + // Update domain and scale for axes; + x.domain([series.xMin, series.xMax]); + xAxis.scale(x); + y.domain([data[data.length - 1][1], data[0][1]]); + yAxis.scale(y); + svg.selectAll(".y.axis").call(yAxis); + svg.selectAll(".x.axis").call(xAxis); + + // Remove existing elements + svg.selectAll('path.area').remove(); + + svg.insert("path",':first-child') // Area/Path to appear behind everything else + .datum(data) + .attr("class", "area") + .attr('fill', 'url(#gradient)') + .attr("d", area) + .on("mouseover", function() { tip.style("display", null); }) + .on("mouseout", function() { tip.style("display", "none"); }) + .on('mousemove', function() { + var xPos = d3.mouse(this)[0], x0 = x.invert(xPos), y0 = func(x0), flip = (xPos > w * 0.75); + tip.attr("transform", "translate(" + x(x0) + "," + y(y0) + ")"); + tip.selectAll('text.label').attr("x", flip? -10 : 10).style("text-anchor", flip? 'end' : 'start'); + tip.select('text.label.x').text(fmtLong(x0) + ' ' + labels.xAxis.unit); + tip.select('text.label.y').text(fmtLong(y0) + ' ' + labels.yAxis.unit); + }); + } + + } + }; +}); \ No newline at end of file diff --git a/app/js/directives/directive-bar-chart.js b/app/js/directives/directive-bar-chart.js index dd27c3d1..e791f585 100644 --- a/app/js/directives/directive-bar-chart.js +++ b/app/js/directives/directive-bar-chart.js @@ -25,76 +25,75 @@ angular.module('app').directive('barChart', ['$rootScope', function ($rootScope) width: '=' }, link: function(scope, element) { - var color = d3.scale.ordinal().range([ "#7b6888", "#6b486b", "#3182bd", "#a05d56", "#d0743c"]), + var color = d3.scale.ordinal().range([ '#7b6888', '#6b486b', '#3182bd', '#a05d56', '#d0743c']), width = scope.width, - height = scope.height, labels = scope.facet.lbls, - fmt = $rootScope[scope.facet.fmt], - properties = scope.facet.prop? [scope.facet.prop] : scope.facet.props, + fmt = scope.facet.fmt, + properties = scope.facet.props, unit = scope.facet.unit, margin = {top: 10, right: 20, bottom: 35, left: 150}, - w = width - margin.left - margin.right, - h = height - margin.top - margin.bottom; + w = width - margin.left - margin.right; // Create chart - var svg = d3.select(element[0]).append("svg") - .attr("width", width) - .attr("height", height) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + var svg = d3.select(element[0]).append('svg').attr('width', width); + var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); // Create and Add tooltip var tip = d3.tip() .attr('class', 'd3-tip') - .html(function(property, propertyIndex, buildIndex) { - return (labels? (labels[propertyIndex] + ": ") : '') + fmt(property.value) + ' ' + unit; + .html(function(property, propertyIndex) { + return (labels? (labels[propertyIndex] + ': ') : '') + fmt(property.value) + ' ' + unit; }); - svg.call(tip); + vis.call(tip); // Create Y Axis SVG Elements - svg.append("g").attr("class", "y axis"); - svg.selectAll('g.y.axis g text').each(insertLinebreaks); + vis.append('g').attr('class', 'y axis'); + vis.selectAll('g.y.axis g text').each(insertLinebreaks); // Create X Axis SVG Elements - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + h + ")") - .append("text") - .attr("y", 30) - .attr("x", w/2) - .attr("dy", ".1em") - .style("text-anchor", "middle") + vis.append('g') + .attr('class', 'x axis') + .append('text') + .attr('y', 30) + .attr('x', w/2) + .attr('dy', '.1em') + .style('text-anchor', 'middle') .text(scope.facet.title + (unit? (' (' + unit + ')') : '')); /** * Watch for changes in the comparison array (ships added/removed, sorting) */ - scope.$watch('data', function() { - var data = scope.data; - var maxVal = d3.max(data, function(d) { return d3.max(properties, function(prop) {return d[prop]; }); }); - var y0 = d3.scale.ordinal().domain(data.map(bName)).rangeRoundBands([0, h],0.3); - var y1 = d3.scale.ordinal().domain(properties).rangeRoundBands([0, y0.rangeBand()]); - var x = d3.scale.linear().range([0, w]).domain([0, maxVal]); - var yAxis = d3.svg.axis().scale(y0).outerTickSize(0).orient("left"); - var xAxis = d3.svg.axis().scale(x).outerTickSize(0).orient("bottom").tickFormat(d3.format('.2s')); + scope.$watchCollection('data', function() { + var data = scope.data, + height = 45 + (25 * data.length), + h = height - margin.top - margin.bottom, + maxVal = d3.max(data, function(d) { return d3.max(properties, function(p) {return d[p]; }); }), + y0 = d3.scale.ordinal().domain(data.map(bName)).rangeRoundBands([0, h],0.3), + y1 = d3.scale.ordinal().domain(properties).rangeRoundBands([0, y0.rangeBand()]), + x = d3.scale.linear().range([0, w]).domain([0, maxVal]), + yAxis = d3.svg.axis().scale(y0).outerTickSize(0).orient('left'), + xAxis = d3.svg.axis().scale(x).outerTickSize(0).orient('bottom').tickFormat(d3.format('.2s')); + + // Update chart size + svg.attr('height', height); // Remove existing elements - svg.selectAll('.ship').remove(); - svg.selectAll('rect').remove(); + vis.selectAll('.ship').remove(); + vis.selectAll('rect').remove(); // Update X & Y Axis - svg.selectAll(".y.axis").call(yAxis); - svg.selectAll(".x.axis").call(xAxis); + vis.selectAll('.y.axis').call(yAxis); + vis.selectAll('.x.axis').attr('transform', 'translate(0,' + h + ')').call(xAxis); // Update Y-Axis labels - svg.selectAll('g.y.axis g text').each(insertLinebreaks); + vis.selectAll('g.y.axis g text').each(insertLinebreaks); - var group = svg.selectAll(".ship") + var group = vis.selectAll('.ship') .data(scope.data, bName) - .enter().append("g") - .attr("class", "g") - .attr("transform", function(build) { return "translate(0," + y0(bName(build)) + ")"; }); + .enter().append('g') + .attr('class', 'g') + .attr('transform', function(build) { return 'translate(0,' + y0(bName(build)) + ')'; }); - group.selectAll("rect") + group.selectAll('rect') .data(function(build) { var o = []; for (var i = 0; i < properties.length; i++) { @@ -102,20 +101,20 @@ angular.module('app').directive('barChart', ['$rootScope', function ($rootScope) } return o; }) - .enter().append("rect") - .attr("height", y1.rangeBand()) - .attr("x",0) - .attr("y", function(d) {return y1(d.name); }) - .attr("width", function(d) { return x(d.value); }) + .enter().append('rect') + .attr('height', y1.rangeBand()) + .attr('x',0) + .attr('y', function(d) {return y1(d.name); }) + .attr('width', function(d) { return x(d.value); }) .on('mouseover', tip.show) .on('mouseout', tip.hide) - .style("fill", function(d) { return color(d.name); }); + .style('fill', function(d) { return color(d.name); }); }); scope.$on('$destroy', function() { tip.destroy(); // Remove the tooltip from the DOM - }) + }); } }; diff --git a/app/js/directives/directive-comparison-table.js b/app/js/directives/directive-comparison-table.js new file mode 100644 index 00000000..a47550a1 --- /dev/null +++ b/app/js/directives/directive-comparison-table.js @@ -0,0 +1,80 @@ +angular.module('app').directive('comparisonTable', ['$state', function ($state) { + + function tblHeader(facets) { + var r1 = ['ShipBuild']; + var r2 = []; + for (var i = 0, l = facets.length; i < l; i++) { + if (facets[i].active) { + var f = facets[i]; + var p = f.props; + var pl = p.length; + r1.push('' , f.lbls[j], ''); + } + } + + r1.push('>', f.title ,''); + } + } + r1.push(''); + r1.push(r2.join('')); + r1.push(''); + return r1.join(''); + } + + function tblBody(facets, builds) { + var body = []; + + if(builds.length === 0) { + return 'No builds added to comparison!'); + var href = $state.href('outfit',{shipId: b.id, code: b.code, bn: b.buildName}); + body.push('', b.name,''); + body.push('', b.buildName,''); + + for (var j = 0, fl = facets.length; j < fl; j++) { + if (facets[j].active) { + var f = facets[j]; + var p = f.props; + for (var k = 0, pl = p.length; k < pl; k++) { + body.push('', f.fmt(b[p[k]]), ' ', f.unit, ''); + } + } + } + body.push(''); + } + + return body.join(''); + } + + return { + restrict: 'A', + + link: function (scope, element) { + var header = angular.element(''); + var body = angular.element(''); + element.append(header); + element.append(body); + + var updateAll = function (){ + header.html(tblHeader(scope.facets)); + body.html(tblBody(scope.facets, scope.builds)); + }; + + scope.$watchCollection('facets', updateAll); + scope.$watch('tblUpdate', updateAll); + scope.$watchCollection('builds', function() { + body.html(tblBody(scope.facets, scope.builds)); + }); + } + }; +}]); \ No newline at end of file diff --git a/app/js/directives/directive-component-select.js b/app/js/directives/directive-component-select.js index 2534c261..8cd5d4ec 100644 --- a/app/js/directives/directive-component-select.js +++ b/app/js/directives/directive-component-select.js @@ -1,4 +1,4 @@ -angular.module('app').directive('componentSelect', function() { +angular.module('app').directive('componentSelect', function () { // Generting the HTML in this manner is MUCH faster than using an angular template. @@ -8,20 +8,34 @@ angular.module('app').directive('componentSelect', function() { var o = opts[i]; var id = o.id || (o.class + o.rating); // Common components' ID is their class and rating list.push('
  • '); + if(o.mode) { list.push(' '); } + list.push(o.class, o.rating); + if(o.mode) { list.push('/' + o.mode); if(o.missile) { list.push(o.missile); } } - if(o.name) list.push(' ' + o.name); + + if(o.name) { + list.push(' ' + o.name); + } + list.push('
  • '); prevClass = o.class; prevRating= o.rating; @@ -49,7 +63,7 @@ angular.module('app').directive('componentSelect', function() { if(groups) { // At present time slots with grouped options (Hardpoints and Internal) can be empty list.push('
    EMPTY
    '); - for (g in groups) { + for (var g in groups) { var grp = groups[g]; var grpCode = grp[Object.keys(grp)[0]].grp; // Nasty operation to get the grp property of the first/any single component list.push('
    ', g, '