PageSourceSearch

https://www.smokeandfumes.org/scripts/controllers/TimelineCtrl.js

js smokeandfumes.org collected 2026-10-02 05:16:30 UTC 8,875 bytes, 270 lines download raw bytes

1(function() {
2  function TimelineCtrl($scope, $stateParams, $state, ShowNav, MomentService, DocumentService, anchorSmoothScroll, $timeout, WhichTimelineService) {
3    /*
4     * SETUP
5     */
6
7    // support old url style
8    // if the url is /moments/{id}, and id is less than or equal to 13 (the previous moments count),
9    // redirect to /fumes/moments/{id}. otherwise try /smoke/moments{id}
10    var idParam = $stateParams.id;
11
12    if ($state.current.name === "moments" && idParam <= 13) {
13      $state.go("fumes_moments", {id: idParam});
14    }
15    else if ($state.current.name === "moments") {
16      $state.go("smoke_moments", {id: idParam});
17    }
18
19    // move the navbar down
20    ShowNav.changeState("down");
21
22    var smokeTitle = document.getElementById("smoke-title");
23    var fumesTitle = document.getElementById("fumes-title");
24    var ampersandTitle = document.getElementById("ampersand-title");
25
26    // when loading a timeline, find which timeline is shown and adjust the title
27    $timeout(function() {
28      ampersandTitle.style.opacity = "0.5";
29      ampersandTitle.style.color = "transparent";
30      ampersandTitle.style.textShadow = "rgba(255, 255, 255, 1.0) 0 0 20px";
31
32      if (WhichTimelineService.timeline() === "fumes") {
33        fumesTitle.style.opacity = "1.0";
34        smokeTitle.style.opacity = "0.5";
35        smokeTitle.style.color = "transparent";
36        smokeTitle.style.textShadow = "rgba(255, 255, 255, 1.0) 0 0 20px";
37      }
38      else if (WhichTimelineService.timeline() === "smoke") {
39        smokeTitle.style.opacity = "1.0";
40        fumesTitle.style.opacity = "0.5";
41        fumesTitle.style.color = "transparent";
42        fumesTitle.style.textShadow = "rgba(255, 255, 255, 1.0) 0 0 20px";
43      }
44    }, 2000);
45
46
47    /**
48     * @desc Setup moments, oppositeTimeline, and background image depending on
49     * our current timeline
50     * @type {Object}
51     */
52    if (WhichTimelineService.timeline() === "fumes") {
53      $scope.moments = MomentService.getFumes();
54      $scope.currentTimeline = "fumes";
55      $scope.timelineBackground = "{'background-image': 'url(/assets/images/oil1.jpg)'}"
56      $scope.oppositeTimeline = "Smoke";
57    } else {
58      $scope.moments = MomentService.getSmoke();
59      $scope.currentTimeline = "smoke";
60      $scope.timelineBackground = "{'background-image': 'url(/assets/images/cigs.jpg)'}"
61      $scope.oppositeTimeline = "Fumes";
62    }
63
64    /**
65     * @desc the number of moments in the database (Firebase array)
66     * @type {Number}
67     */
68    var momentsLength;
69
70    /**
71     * @function setMomentsLength
72     * @desc find the number of momens in the firebase array and
73     * set momensLength to this number
74     */
75    $scope.moments.$loaded().then(function setMomentsLength(moments) {
76      momentsLength = $scope.moments.length;
77
78      moments.forEach(function (moment) {
79        moment.documentObjects = [];
80
81        if (moment.documents) {
82          moment.documents.forEach(function (documentId) {
83            DocumentService.getById(documentId).then(function (document) {
84              moment.documentObjects.push(document);
85            });
86          });
87        }
88      });
89    })
90
91    /**
92     * @function toggleTimeline
93     * @desc given the current moment's related moment id, go to the opposite timeline
94     * and scroll to that id
95     */
96    $scope.toggleTimeline = function(relatedMomentId) {
97      id = Number(relatedMomentId);
98
99      if (WhichTimelineService.timeline() === "fumes") {
100        $state.go("smoke_moments", {id: id});
101      } else {
102        $state.go("fumes_moments", {id: id});
103      }
104    };
105
106    /**
107     * @function getDocument
108     * @desc create a new Firebase object for the provided document
109     * and find the year and authors for the timeline display
110     * @param {Number} id of the desired document
111     * @returns {String} "year-of-document, document-authors"
112     */
113    $scope.getDocument = function(id) {
114      return DocumentService.getById(id).then(function (doc) {
115        return doc;
116      });
117    };
118
119    /**
120     * @function gotoState
121     * @desc transition to the appropriate state given an element id
122     * @param {String} id of the desired element
123     */
124    $scope.gotoState = function(id) {
125      var state = $state.current.name;
126
127      if (WhichTimelineService.timeline() === "smoke") {
128        switch(id) {
129          case "top":
130            $state.go("smoke", {id: undefined}, {notify: false});
131            break;
132          case "video":
133            $state.go("smoke_video", {id: undefined}, {notify: false});
134            break;
135          default:
136            $state.go("smoke_moments", {id: id}, {notify: false});
137        }
138      }
139      else if (WhichTimelineService.timeline() === "fumes") {
140        switch(id) {
141          case "top":
142            $state.go("fumes", {id: undefined}, {notify: false});
143            break;
144          case "video":
145            $state.go("fumes_video", {id: undefined}, {notify: false});
146            break;
147          default:
148            $state.go("fumes_moments", {id: id}, {notify: false});
149        }
150      }
151    }
152
153    /**
154     * @function gotoElement
155     * @desc scroll to the provided element
156     * the upper and lower bounds are set by the number of moments in the
157     * momentsRef
158     * @param {String} id of the desired element
159     */
160    $scope.gotoElement = function(id) {
161      if (id === "firstMoment") {
162        id = "moment-" + $scope.moments[0].id;
163      }
164      // get the length of fumes moments
165      // if the id is > fumes moments length - 1, id = id - fumesMomentsLength
166
167
168      // scroll to the element
169      // if moment doesn't exist by that id, go to the top
170      try {
171        anchorSmoothScroll.scrollTo(id);
172        // this is redundant but ensures that the indicators are always properly
173        // adjusted if in-view doesn't act quick enough.
174        $timeout(function() {
175          if (id !== "smoke-video" && id !== "fumes-video") {
176            // adjust indicators based on the moment's id
177            $scope.adjustIndicators(id.substr(7));
178            // set url
179            $scope.gotoState(id.substr(7));
180          }
181        }, 1000);
182      }
183      catch(e) {
184        id = "top";
185        anchorSmoothScroll.scrollTo(id);
186      }
187    };
188
189    /**
190     * @function scrollToMoment
191     * @desc if there's an id parameter specified in the url,
192     * scroll to it
193     */
194    $scope.moments.$loaded().then(function scrollToMoment() {
195      var state = $state.current.name;
196
197      // check that we're in a timeline or moments state and we have an id
198      if ((WhichTimelineService.timeline() === "smoke" || WhichTimelineService.timeline() === "fumes") && $stateParams.id) {
199        $scope.$$postDigest(function () {
200          // get the moment element by the id param
201          var moment = document.getElementById('moment-' + $stateParams.id);
202          // if we found a matching moment element
203          if (moment) {
204            // scroll to that moment
205            moment.scrollIntoView({block: "start", behavior: "smooth"});
206          }
207        });
208      }
209    });
210
211    /**
212     * @desc The id of the indicator, set in adjustIndicators when a moment is
213     *  in view
214     * @type {Number}
215     */
216    var currentMomentId;
217
218    /**
219     * @function indicatorMargin
220     * @desc dynamically set the margin of each indicator so they stack nicely
221     * @returns {Object} a style object used in ng-style
222     */
223    $scope.indicatorMargin = function(index) {
224      var iInverse = momentsLength - index - 1;
225
226      return {"margin": ((index * 1.5) + 0.5) + "em 0 " + ((iInverse * 1.5) + 0.5) + "em 0"};
227    };
228
229    /**
230     * @function indicatorPassed
231     * @desc the position of an indicator -- if the provided momentId
232     *  is less than the currentMomentId set in adjustIndicators, that indicator has passed
233     * @param The id of the indicator/moment
234     * @returns {Boolean} true if indicator has been passed, false otherwise
235     */
236    $scope.indicatorPassed = function(momentId) {
237      if (momentId < currentMomentId) {
238        return true;
239      } else {
240        return false;
241      }
242    };
243
244    /**
245     * @function indicatorActive
246     * @desc Does this indicator match the current moment?
247     * @param The id of the indicator/moment
248     * @returns {Boolean} true if indicator index matches the current moment, false otherwise
249     */
250    $scope.indicatorActive = function(momentId) {
251      if (momentId == currentMomentId) {
252        return true;
253      } else {
254        return false;
255      }
256    }
257
258    /**
259     * @function adjustIndicators
260     * @desc Set the currentMomentId to the provided indicator's id
261     * @param The id of the indicator/moment
262     */
263    $scope.adjustIndicators = function(momentId) {
264      currentMomentId = momentId;
265    }
266  }
267  angular
268    .module("knew")
269    .controller("TimelineCtrl", TimelineCtrl)
270})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.