time_table 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,206 @@
1
+ module TimeTable
2
+ module TimetableCalendarHelper
3
+ def timetable_calendar(bounds:, range: 7, scale: 60, clip: 15, frozen: false, **options, &block)
4
+ timetable_calendar = TimetableCalendar.new(bounds: bounds, range: range, view: self, query_params: request.query_parameters)
5
+ timetable_calendar.set_multi_timetable(scale: scale, clip: clip, frozen: frozen, view: self)
6
+
7
+ options[:class] = "#{options[:class]} timetable-calendar"
8
+ content_tag :div, **options do
9
+ yield timetable_calendar
10
+ end
11
+ end
12
+
13
+ class Timetable
14
+ attr_accessor :start_date, :end_date, :start_time, :end_time, :dates, :scale, :clip, :frozen, :view, :events, :template_event
15
+
16
+ def initialize(start_date:, end_date:, view:, start_time: nil, end_time: nil, scale: 60, clip: 15, frozen: false)
17
+ @start_date = start_date
18
+ @end_date = end_date
19
+ @dates = start_date..end_date
20
+ @scale = scale
21
+ @clip = clip
22
+ @frozen = frozen
23
+ @view = view
24
+ @events = {}
25
+ @start_time = start_time || start_date.beginning_of_day
26
+ @end_time = end_time || start_date.end_of_day
27
+ end
28
+
29
+ def register_events_template(model)
30
+ @template_event = model
31
+ end
32
+
33
+ def register_events_for_column(day, events)
34
+ @events[day] = events
35
+ end
36
+
37
+ def render_timetable_with_events(&block)
38
+ @view.render(layout: "time_table/timetable", locals: { timetable: self }, &block)
39
+ end
40
+ end
41
+
42
+ class TimetableCalendar
43
+ attr_accessor :calendar_boundaries, :current_date_range, :view, :query_params, :multi_timetable
44
+
45
+ delegate :register_events_for_column, :render_timetable_with_events, :register_events_template, to: :multi_timetable
46
+
47
+ MAX_NUMBER_OF_DAYS = 7
48
+
49
+ def initialize(bounds:, range: 7, query_params: {}, view: nil)
50
+ @calendar_boundaries = bounds
51
+ @query_params = query_params
52
+ @view = view
53
+
54
+ @current_date_range = get_bounded_date_range(range)
55
+ end
56
+
57
+ def set_multi_timetable(**options)
58
+ @multi_timetable = Timetable.new(start_date: current_start_date, end_date: current_end_date, view: view, **options)
59
+ end
60
+
61
+ ######################
62
+ ## HEADER RENDERING ##
63
+ ######################
64
+
65
+ def render_days(&block)
66
+ @view.content_tag :div, class: "timetable-headers" do
67
+ @view.concat(current_date_range.map do |day|
68
+ @view.content_tag :div, class: "timetable-header" do
69
+ yield(day)
70
+ end
71
+ end.join("").html_safe)
72
+ end
73
+ end
74
+
75
+ #################
76
+ ## INFORMATION ##
77
+ #################
78
+
79
+ def months_string
80
+ if current_start_date.year == current_end_date.year
81
+ if current_start_date.month == current_end_date.month
82
+ "#{current_start_date.strftime('%B %Y')}"
83
+ else
84
+ "#{current_start_date.strftime('%B')} - #{current_end_date.strftime('%B %Y')}"
85
+ end
86
+ else
87
+ "#{current_start_date.strftime('%B %Y')} - #{current_end_date.strftime('%B %Y')}"
88
+ end
89
+ end
90
+
91
+ #################
92
+ ## QUERY LINKS ##
93
+ #################
94
+
95
+ def query_link(text = nil, query:, **params, &block)
96
+ active = query.reduce(true) do |acc, (key, value)|
97
+ acc && send(key) == value
98
+ end
99
+
100
+ params[:class] = "#{params[:class]} active" if active
101
+ link_to(text, @query_params.merge(query), **params, &block)
102
+ end
103
+
104
+ ######################
105
+ ## NAVIGATION LINKS ##
106
+ ######################
107
+
108
+ def previous_link(text = nil, **params, &block)
109
+ if current_start_date == calendar_start_boundary
110
+ return disabled_nav_link(text, **params, &block)
111
+ end
112
+
113
+ previous_day = current_start_date - current_number_of_days
114
+ previous_day = calendar_start_boundary if previous_day < calendar_start_boundary
115
+
116
+ link_to(text, @query_params.merge(start_date: previous_day), **params, &block)
117
+ end
118
+
119
+ def next_link(text = nil, **params, &block)
120
+ if current_start_date + current_number_of_days.days > calendar_end_boundary
121
+ return disabled_nav_link(text, **params, &block)
122
+ end
123
+
124
+ next_day = current_start_date + current_number_of_days.days
125
+ next_day = calendar_end_boundary - current_number_of_days.days + 1 if next_day + current_number_of_days.days > calendar_end_boundary
126
+
127
+ link_to(text, @query_params.merge(start_date: next_day), **params, &block)
128
+ end
129
+
130
+ def disabled_nav_link(text = nil, **params, &block)
131
+ params[:class] = "#{params[:class]} disabled"
132
+ link_to(text, "", **params, &block)
133
+ end
134
+
135
+ def link_to(*args, **params, &block)
136
+ @view.link_to *args.compact, **params, &block
137
+ end
138
+
139
+ #######################
140
+ ## ATTRIBUTE READERS ##
141
+ #######################
142
+
143
+ def current_start_date
144
+ @current_start_date ||= @current_date_range.first
145
+ end
146
+
147
+ alias_method :start_date, :current_start_date
148
+
149
+ def current_end_date
150
+ @current_end_date ||= @current_date_range.last
151
+ end
152
+
153
+ alias_method :end_date, :current_end_date
154
+
155
+ def current_number_of_days
156
+ @current_number_of_days ||= @current_date_range.count
157
+ end
158
+
159
+ alias_method :number_of_days, :current_number_of_days
160
+
161
+ def calendar_start_boundary
162
+ @calendar_start_boundary ||= calendar_boundaries.first
163
+ end
164
+
165
+ def calendar_end_boundary
166
+ @calendar_end_boundary ||= calendar_boundaries.last
167
+ end
168
+
169
+ def calendar_limit
170
+ @calendar_limit ||= calendar_boundaries.count
171
+ end
172
+
173
+ private
174
+
175
+ ############################
176
+ ## DATE RANGE CALCULATION ##
177
+ ############################
178
+
179
+ def get_bounded_date_range(range)
180
+ bounded_number_of_days = bounded_number_of_days(range)
181
+ bounded_start_date = bounded_start_date(bounded_number_of_days)
182
+ computed_end_date = computed_end_date(bounded_start_date, bounded_number_of_days)
183
+
184
+ (bounded_start_date..computed_end_date)
185
+ end
186
+
187
+ def bounded_number_of_days(range)
188
+ selected_number_of_days = query_params[:number_of_days]&.to_i || range
189
+ max_number_of_days = [MAX_NUMBER_OF_DAYS, calendar_limit].min
190
+ selected_number_of_days.clamp(1, max_number_of_days)
191
+ end
192
+
193
+ def bounded_start_date(range)
194
+ selected_start_date = query_params[:start_date]&.to_date || calendar_start_boundary
195
+ max_start_date = calendar_end_boundary - range.days + 1 # Should this use .days?
196
+ selected_start_date.clamp(calendar_start_boundary, max_start_date)
197
+ end
198
+
199
+ def computed_end_date(start_date, range)
200
+ selected_end_date = query_params[:end_date]&.to_date || start_date + range.days - 1
201
+ min_end_date = calendar_start_boundary + range.days - 1
202
+ selected_end_date.clamp(min_end_date, calendar_end_boundary)
203
+ end
204
+ end
205
+ end
206
+ end
@@ -23,11 +23,5 @@
23
23
  <% end %>
24
24
  </div>
25
25
 
26
- <div class="timetable-canvas" data-time-table-target="canvas">
27
- <div class="timetable-events" data-time-table-target="eventsList">
28
- <% events.each do |event| %>
29
- <%= yield event %>
30
- <% end %>
31
- </div>
32
- </div>
26
+ <%= yield timetable %>
33
27
  <% end %>
@@ -0,0 +1,49 @@
1
+ <%= content_tag(:div, class: "timetable loading #{'frozen' if timetable.frozen}", data: {
2
+ controller: "timetable",
3
+ timetable_frozen_param: timetable.frozen,
4
+ timetable_clip_size: timetable.clip,
5
+ timetable_start_time: timetable.start_time.iso8601,
6
+ timetable_end_time: timetable.end_time.iso8601,
7
+ }, style: "--hour-scale: #{timetable.scale}; --timestamp-width: 20px;") do %>
8
+ <%= content_tag(:div, class: "timestamps") do %>
9
+ <% 24.times do |hour| %>
10
+ <div class="timestamp" data-timetable-target="timestamp">
11
+ <div class="label" data-action="mousedown->timetable#startDragEvent" data-time-table-drag-event-param="rescale">
12
+ <%= hour == 0 ? "12 AM" : (hour > 12 ? "#{hour - 12} PM" : "#{hour} AM") %>
13
+ </div>
14
+ </div>
15
+ <% end %>
16
+ <% end %>
17
+
18
+ <%= content_tag(:div, class: "timetable-canvas", data: {
19
+ timetable_target: "canvas"
20
+ }) do %>
21
+ <% timetable.dates.each do |column| %>
22
+ <%= content_tag(:div, class: "timetable-column column", data: {
23
+ action: "
24
+ mousedown->timetable#startDragEvent
25
+ mouseup->timetable#stopDragEvent
26
+ mousemove->timetable#drag
27
+ mouseenter->timetable#changeColumn
28
+ ",
29
+ timetable_drag_event_param: "create",
30
+ timetable_column_param: "#{column}",
31
+ timetable_target: "column",
32
+ }) do %>
33
+ <%= content_tag :div, class: "timetable-skins", data: { timetable_target: "skins" } do %>
34
+ <%= content_tag :div, "", class: "timetable-skin", data: { timetable_target: "skin" } %>
35
+ <% end %>
36
+ <%= content_tag :div, class: "timetable-events", data: { timetable_target: "eventsList", timetable_event_list: column } do %>
37
+ <% timetable.events[column].each do |event, timetable| %>
38
+ <%= yield event %>
39
+ <% end %>
40
+ <% end %>
41
+ <% end %>
42
+ <% end %>
43
+
44
+ <%= content_tag :template, class: "timetable-event-template hidden", data: { timetable_target: "template" } do %>
45
+ <%= yield timetable.template_event %>
46
+ <% end %>
47
+ <% end %>
48
+ <% end %>
49
+
@@ -1,3 +1,3 @@
1
1
  module TimeTable
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.7"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hadik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-09 00:00:00.000000000 Z
11
+ date: 2025-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,23 +38,24 @@ files:
38
38
  - app/assets/javascript/time_table/application.js
39
39
  - app/assets/javascript/time_table/controllers/application.js
40
40
  - app/assets/javascript/time_table/controllers/index.js
41
- - app/assets/javascript/time_table/controllers/time_table_controller.js
42
41
  - app/assets/javascript/time_table/controllers/time_table_controller_old.js
43
- - app/assets/javascript/time_table/controllers/time_table_controller_pre_time_keeper.js
42
+ - app/assets/javascript/time_table/controllers/timetable_controller.js
44
43
  - app/assets/javascript/time_table/helpers/drag_event_state.js
45
44
  - app/assets/javascript/time_table/helpers/scroll_frame.js
46
45
  - app/assets/javascript/time_table/helpers/time_keeper.js
47
46
  - app/assets/javascript/time_table/helpers/time_table_renderer.js
48
47
  - app/assets/stylesheets/time_table/application.css
49
- - app/assets/stylesheets/time_table/time_table.css
48
+ - app/assets/stylesheets/time_table/timetable.css
50
49
  - app/controllers/time_table/application_controller.rb
51
50
  - app/helpers/time_table/application_helper.rb
52
- - app/helpers/time_table/time_table_helper.rb
51
+ - app/helpers/time_table/time_table_old_helper.rb
52
+ - app/helpers/time_table/timetable_calendar_helper.rb
53
53
  - app/jobs/time_table/application_job.rb
54
54
  - app/mailers/time_table/application_mailer.rb
55
55
  - app/models/time_table/application_record.rb
56
56
  - app/views/layouts/time_table/application.html.erb
57
- - app/views/time_table/_time_table.html.erb
57
+ - app/views/time_table/_time_table_old.html.erb
58
+ - app/views/time_table/_timetable.html.erb
58
59
  - config/importmap.rb
59
60
  - config/routes.rb
60
61
  - lib/tasks/time_table_tasks.rake
@@ -1,350 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
- import ScrollFrame from "../helpers/scroll_frame.js"
3
- import TimeTableRenderer from "../helpers/time_table_renderer.js"
4
-
5
- export default class extends Controller {
6
- static targets = ["canvas", "eventsList", "event", "eventName", "eventTime", "timestamp"]
7
-
8
- static UNITS = {
9
- hours: 3_600_000,
10
- minutes: 60_000,
11
- seconds: 1_000
12
- }
13
-
14
- connect() {
15
- this.startTime = new Date(this.element.dataset.timetableStartTime);
16
- this.endTime = new Date(this.element.dataset.timetableEndTime);
17
- this.extendedStartTime = this.startTime;
18
- this.extendedEndTime = this.endTime;
19
- this.clipSize = this.element.dataset.timetableClipSize;
20
-
21
- let topPadding = parseInt(window.getComputedStyle(this.element).paddingTop, 10);
22
-
23
- this.scrollHeight = this.element.scrollHeight - topPadding;
24
- this.scrollFrame = new ScrollFrame(this.element, { origin: topPadding });
25
-
26
- this.dragging = false;
27
- this.dragEvent = {};
28
- this.scrollEvent = {};
29
-
30
- this.timeScope = this.constructor.UNITS.hours;
31
- this.timeMetric = this.constructor.UNITS.minutes;
32
- this.metricConversion = this.timeScope / this.timeMetric;
33
-
34
- this.scale = 60;
35
-
36
- this.eventTargets.forEach((event) => {
37
- TimeTableRenderer.setSpecialClasses(event);
38
- });
39
- }
40
-
41
- dragScreenShot(event) {
42
- let relativePosition = this.scrollFrame.relativeCursorPosition(event);
43
-
44
- return {
45
- position: relativePosition,
46
- time: this.#timeAtPosition(relativePosition.scroll.y),
47
- target: this.targetScreenShot(this.dragEvent.target)
48
- }
49
- }
50
-
51
- targetScreenShot(target) {
52
- if(!target) {
53
- return null;
54
- }
55
-
56
- let relativePosition = this.scrollFrame.relativePosition(target.getBoundingClientRect().left, target.getBoundingClientRect().top);
57
-
58
- let height = target.offsetHeight;
59
-
60
- return {
61
- height: height,
62
- position: relativePosition,
63
- startTime: this.#timeAtPosition(relativePosition.scroll.y),
64
- endTime: this.#timeAtPosition(relativePosition.scroll.y + height),
65
- }
66
- }
67
-
68
- startDragEvent(event) {
69
- event.preventDefault();
70
- event.stopPropagation();
71
-
72
- this.dragging = true;
73
-
74
- this.dragEvent.type = event.params.dragEvent;
75
- this.dragEvent.target = event.currentTarget.closest(".event");
76
- this.dragEvent.origin = this.dragScreenShot(event);
77
- this.dragEvent.current = this.dragEvent.origin;
78
-
79
- // this.dragEventObject = new DragState({
80
- // type: event.params.dragEvent,
81
- // scrollFrame: this.scrollFrame,
82
- // target: event.currentTarget.closest(".event"),
83
- // event: event
84
- // })
85
-
86
- // console.log(this.dragEventObject);
87
-
88
- // this.dragEvent = new DragEvent({
89
- // scrollFrame: this.scrollFrame, event: event, target: event.currentTarget.closest(".event")});
90
-
91
-
92
-
93
- this.#setDragEventListeners();
94
- }
95
-
96
- stopDragEvent(event) {
97
- event.preventDefault();
98
-
99
- this.dragging = false;
100
- this.dragEvent = {};
101
-
102
- this.stopScroll();
103
- this.#removeDragEventListeners();
104
- }
105
-
106
- drag(event) {
107
- if(this.dragging) {
108
- this.dragEvent.previous = this.dragEvent.current;
109
- this.dragEvent.current = this.dragScreenShot(event);
110
- this.dragEvent.event = event;
111
-
112
- // Calls dragResize, dragMove, dragCreate, etc.
113
- this.#invokeDragMethodFor(this.dragEvent.type);
114
-
115
- if(this.dragEvent.type != undefined && this.dragEvent.type != "rescale") {
116
- this.checkScroll();
117
- }
118
- }
119
- }
120
-
121
- //////////////////
122
- // Drag Methods //
123
- //////////////////
124
-
125
- dragCreate(event) {
126
- let timeBoundaries = this.#timeBoundaries(this.dragEvent.current.time.clipped, this.dragEvent.origin.time.clipped);
127
- let eventElement = TimeTableRenderer.createEventElement(timeBoundaries);
128
-
129
- this.eventsListTarget.appendChild(eventElement);
130
- this.dragEvent.target = eventElement;
131
- this.dragEvent.origin.target = this.targetScreenShot(eventElement);
132
- this.dragEvent.current.target = this.dragEvent.origin.target;
133
- this.dragEvent.type = "resize";
134
- }
135
-
136
- dragResize(event) {
137
- let timeBoundaries = this.#timeBoundaries(this.dragEvent.current.time.clipped, this.dragEvent.origin.target.startTime.real);
138
- TimeTableRenderer.updateEventElement(this.dragEvent.target, timeBoundaries);
139
- this.dragEvent.current.target = this.targetScreenShot(this.dragEvent.target);
140
- }
141
-
142
- dragMove(event) {
143
- let timeChange = (this.dragEvent.current.time.clipped - this.dragEvent.origin.time.clipped);
144
- let updatedStartTime = new Date(this.dragEvent.origin.target.startTime.real.getTime() + timeChange)
145
- let updatedEndTime = new Date(this.dragEvent.origin.target.endTime.real.getTime() + timeChange);
146
-
147
- let timeBoundaries = this.#timeBoundaries(updatedStartTime, updatedEndTime);
148
-
149
- TimeTableRenderer.updateEventElement(this.dragEvent.target, timeBoundaries);
150
- this.dragEvent.current.target = this.targetScreenShot(this.dragEvent.target);
151
- }
152
-
153
- dragRescale(event) {
154
- let delta = this.dragEvent.previous.position.scroll.y - this.dragEvent.current.position.scroll.y;
155
- let newScale = Math.max(30, Math.min(300, this.scale - (delta)));
156
- this.element.style.setProperty("--hour-scale", newScale);
157
- let scaleChange = newScale / this.scale;
158
-
159
- this.scrollHeight = this.element.scrollHeight - 20;
160
- this.scale = newScale;
161
- this.setClipSize(newScale);
162
-
163
- this.eventTargets.forEach((event) => {
164
- event.style.setProperty("height", `${event.offsetHeight * (scaleChange)}px`);
165
- event.style.setProperty("top", `${event.offsetTop * (scaleChange)}px`);
166
- TimeTableRenderer.setSpecialClasses(event);
167
- });
168
- }
169
-
170
- ////////////////////
171
- // Scroll Methods //
172
- ////////////////////
173
-
174
- checkScroll() {
175
- // TODO - Refactor
176
- let currentFrameY = this.dragEvent.current.position.frame.y;
177
- if(currentFrameY < 30) {
178
- let distance = Math.abs(currentFrameY - 30);
179
- let direction = -1;
180
- this.setScroll(distance, direction);
181
- } else if (currentFrameY > this.scrollFrame.frame.height - 30) {
182
- let distance = Math.abs(currentFrameY - (this.scrollFrame.frame.height - 30));
183
- let direction = +1;
184
- this.setScroll(distance, direction);
185
- } else {
186
- this.stopScroll();
187
- }
188
- }
189
-
190
- static SCROLL_SPEEDS = [
191
- { max: 30, speed: 1 },
192
- { max: 50, speed: 2 },
193
- { max: 100, speed: 3 },
194
- { max: 150, speed: 5 },
195
- { max: 250, speed: 10 },
196
- { max: Infinity, speed: 15}
197
- ]
198
-
199
- setScroll(distance, direction) {
200
- this.scrollEvent.step = (this.constructor.SCROLL_SPEEDS.find(range => distance < range.max)?.speed || 10) * direction;
201
-
202
- if(!this.scrollEvent.timeout) {
203
- this.scroll();
204
- }
205
- }
206
-
207
- scroll() {
208
- this.scrollEvent.timeout = setTimeout(() => {
209
- this.element.scrollTop += this.scrollEvent.step;
210
- if(this.element.scrollTop == 0) {
211
- this.insertTimestampAbove();
212
- }
213
-
214
- if(this.element.scrollTop + this.element.clientHeight >= this.scrollHeight) {
215
- this.insertTimestampBelow();
216
- }
217
-
218
- this.scroll();
219
- this.drag(this.dragEvent.event);
220
- }, 1);
221
- }
222
-
223
- insertTimestampAbove() {
224
- }
225
-
226
- insertTimestampBelow() {
227
- // this.dragEvent.inserting = true;
228
- // Add 1 hour
229
- let time = new Date(this.endTime.getTime());
230
- time.setHours(time.getHours() + 1);
231
- this.endTime = time;
232
- let timestampDiv = TimeTableRenderer.timestamp(time);
233
- console.log(timestampDiv);
234
- this.element.querySelector(".timestamps").appendChild(timestampDiv);
235
- this.scrollHeight = this.element.scrollHeight - 20;
236
- }
237
-
238
- stopScroll() {
239
- if(this.scrollEvent.timeout) {
240
- clearTimeout(this.scrollEvent.timeout);
241
- this.scrollEvent = {};
242
- }
243
- }
244
-
245
- /////////////////////
246
- // Time & Position //
247
- /////////////////////
248
-
249
- #timeBoundaries(timeA, timeB) {
250
- let startTime = new Date(Math.min(timeA, timeB));
251
- let endTime = new Date(Math.max(timeA, timeB));
252
-
253
- if (endTime - startTime < this.clipSize * 60 * 1000) {
254
- endTime = new Date(startTime.getTime() + (this.clipSize * 60 * 1000));
255
- }
256
-
257
- return {
258
- start: { time: startTime, location: this.#positionOfTime(startTime) },
259
- end: { time: endTime, location: this.#positionOfTime(endTime) }
260
- };
261
- }
262
-
263
- #timeAtPosition(relativeScrollY) {
264
- let scopeOrdinal = Math.trunc(relativeScrollY / this.scale); // Eg "Hours from start"
265
- let positionInScope = (relativeScrollY % this.scale) / this.scale;
266
- let scopeMeasure = Math.trunc(positionInScope * this.metricConversion)
267
- let clippedScopeMeasure = Math.floor(scopeMeasure / this.clipSize) * this.clipSize;
268
- let millisecondsFromStart = (scopeOrdinal * this.timeScope) + (scopeMeasure * this.timeMetric);
269
- let clippedMillisecondsFromStart = (scopeOrdinal * this.timeScope) + (clippedScopeMeasure * this.timeMetric);
270
-
271
- return {
272
- real: new Date(this.startTime.getTime() + millisecondsFromStart), // For some reason 1 second is added to real each time you change it.
273
- clipped: new Date(this.startTime.getTime() + clippedMillisecondsFromStart),
274
- }
275
- }
276
-
277
- #positionOfTime(time) {
278
- let timeFromStart = time - this.startTime;
279
- let scopeFromStart = Math.floor(timeFromStart / this.timeScope);
280
- let metricFromScope = Math.floor((timeFromStart % this.timeScope) / this.timeMetric);
281
- let pixelsFromStart = (scopeFromStart * this.scale) + (metricFromScope * this.scale / this.metricConversion);
282
- return pixelsFromStart;
283
- }
284
-
285
-
286
- ////////////////
287
- // Invokation //
288
- ////////////////
289
-
290
- #invokeDragMethodFor(type) {
291
- if(!type) {
292
- console.error("No drag type provided");
293
- return;
294
- }
295
- let capitalizedType = type.charAt(0).toUpperCase() + type.slice(1);
296
-
297
- if (this[`drag${capitalizedType}`]) {
298
- this[`drag${capitalizedType}`]();
299
- } else {
300
- console.error(`No drag method found for type: ${type}`);
301
- }
302
- }
303
-
304
- /////////////
305
- // Helpers //
306
- /////////////
307
-
308
- static CLIP_SCALES = [
309
- { max: 40, clipSize: 60 },
310
- { max: 50, clipSize: 30 },
311
- { max: 150, clipSize: 15 },
312
- { max: 280, clipSize: 5 },
313
- { max: Infinity, clipSize: 1}
314
- ]
315
-
316
- setClipSize(scale) {
317
- this.clipSize = this.constructor.CLIP_SCALES.find(range => scale < range.max)?.clipSize || 15;
318
- }
319
-
320
- #setDragEventListeners() {
321
- document.addEventListener("mousemove", this.drag.bind(this));
322
- document.addEventListener("mouseup", this.stopDragEvent.bind(this));
323
- document.addEventListener("mouseleave", this.stopDragEvent.bind(this));
324
- }
325
-
326
- #removeDragEventListeners() {
327
- document.removeEventListener("mousemove", this.drag.bind(this));
328
- document.removeEventListener("mouseup", this.stopDragEvent.bind(this));
329
- document.removeEventListener("mouseleave", this.stopDragEvent.bind(this));
330
- }
331
- }
332
-
333
- // class DragState {
334
- // constructor({ type, scrollFrame, target, event }) {
335
- // this.type = type;
336
- // this.scrollFrame = scrollFrame;
337
- // this.target = target;
338
- // this.event = event;
339
- // this.captureOriginSnapshot();
340
- // }
341
-
342
- // captureOriginSnapshot() {
343
- // this.current = this.origin;
344
- // }
345
-
346
- // captureSnapshot() {
347
- // this.previous = this.current;
348
-
349
- // }
350
- // }