pageflow-sitemap 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.jshintrc +18 -0
- data/Gemfile +24 -0
- data/LICENSE.md +20 -0
- data/README.md +47 -0
- data/Rakefile +32 -0
- data/app/assets/images/pageflow/sitemap/.keep +0 -0
- data/app/assets/javascripts/pageflow/sitemap/.keep +0 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/controllers/abstract_controller.js +68 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/controllers/editor_mode_controller.js +301 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/controllers/fragment_parser.js +31 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/controllers/selection_mode_controller.js +37 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/controllers/selection_navigator.js +43 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/behaviors/mouse_wheel.js +43 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/behaviors/multi_drag.js +73 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/behaviors/scroll_and_zoom.js +286 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/behaviors/selection_rect.js +104 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/behaviors/tooltip_target.js +24 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/graph_view.js +277 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/layout/chapter_collision.js +33 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/layout/collision.js +116 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/layout/dragging_decorator.js +58 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/layout/grid.js +238 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/layout/link_dragging_decorator.js +42 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/layout.js +94 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/options.js +25 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/paths/follow_path.js +36 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/paths/linkpath.js +64 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/paths/successor_path.js +49 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/utils.js +33 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/view_model.js +202 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/add_button_view.js +28 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/chapter_placeholders_view.js +22 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/chapters_view.js +89 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/group_view.js +104 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/page_links_view.js +7 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/pages_view.js +112 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/selectable_links_view.js +104 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/storylines_view.js +86 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/successor_links_view.js +7 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3/views/text_label_view.js +45 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/d3.js +20 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/feature.js +126 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/models/selection.js +41 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/templates/scroll_bar.jst.ejs +2 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/templates/sitemap.jst.ejs +85 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/views/scroll_bar_view.js +130 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/views/scroll_pane_view.js +73 -0
- data/app/assets/javascripts/pageflow/sitemap/editor/views/sitemap_view.js +137 -0
- data/app/assets/javascripts/pageflow/sitemap/editor.js +14 -0
- data/app/assets/javascripts/pageflow/sitemap/feature.js +3 -0
- data/app/assets/javascripts/pageflow/sitemap/scroll_navigator.js +112 -0
- data/app/assets/javascripts/pageflow/sitemap.js +5 -0
- data/app/assets/stylesheets/pageflow/sitemap/.keep +0 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/add_button.scss +29 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/chapter_placeholders.scss +14 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/chapters.scss +62 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/page_links.scss +19 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/pages.scss +78 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/scroll_bar.css.scss +33 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/scroll_pane.scss +15 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/selectable_links.scss +88 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/selection_rect.scss +12 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/storylines.scss +59 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/successor_links.scss +42 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/text_label.scss +23 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor/toolbar.css.scss +45 -0
- data/app/assets/stylesheets/pageflow/sitemap/editor.css.scss +96 -0
- data/config/locales/de.yml +16 -0
- data/config/locales/en.yml +48 -0
- data/config/locales/new/help_button.de.yml +7 -0
- data/config/locales/new/help_button.en.yml +7 -0
- data/config/locales/new/tooltips.de.yml +11 -0
- data/config/locales/new/tooltips.en.yml +11 -0
- data/config/routes.rb +7 -0
- data/config/spring.rb +1 -0
- data/exec/rails +12 -0
- data/exec/spring +18 -0
- data/exec/teaspoon +17 -0
- data/lib/pageflow/sitemap/engine.rb +10 -0
- data/lib/pageflow/sitemap/plugin.rb +11 -0
- data/lib/pageflow/sitemap/version.rb +5 -0
- data/lib/pageflow-sitemap.rb +9 -0
- data/pageflow-sitemap.gemspec +29 -0
- data/spec/d/r/.gitignore +16 -0
- data/spec/d/r/README.rdoc +28 -0
- data/spec/d/r/Rakefile +6 -0
- data/spec/d/r/app/admin/dashboard.rb +33 -0
- data/spec/d/r/app/assets/images/.keep +0 -0
- data/spec/d/r/app/assets/javascripts/active_admin.js.coffee +2 -0
- data/spec/d/r/app/assets/javascripts/application.js +16 -0
- data/spec/d/r/app/assets/javascripts/pageflow/application.js +1 -0
- data/spec/d/r/app/assets/javascripts/pageflow/editor.js +4 -0
- data/spec/d/r/app/assets/stylesheets/active_admin.css.scss +18 -0
- data/spec/d/r/app/assets/stylesheets/application.css +13 -0
- data/spec/d/r/app/assets/stylesheets/pageflow/application.css.scss +1 -0
- data/spec/d/r/app/assets/stylesheets/pageflow/editor.css.scss +1 -0
- data/spec/d/r/app/controllers/application_controller.rb +5 -0
- data/spec/d/r/app/controllers/concerns/.keep +0 -0
- data/spec/d/r/app/helpers/application_helper.rb +2 -0
- data/spec/d/r/app/mailers/.keep +0 -0
- data/spec/d/r/app/models/.keep +0 -0
- data/spec/d/r/app/models/ability.rb +12 -0
- data/spec/d/r/app/models/concerns/.keep +0 -0
- data/spec/d/r/app/models/user.rb +9 -0
- data/spec/d/r/app/views/layouts/application.html.erb +14 -0
- data/spec/d/r/bin/bundle +3 -0
- data/spec/d/r/bin/rails +4 -0
- data/spec/d/r/bin/rake +4 -0
- data/spec/d/r/config/application.rb +31 -0
- data/spec/d/r/config/boot.rb +4 -0
- data/spec/d/r/config/database.yml +39 -0
- data/spec/d/r/config/environment.rb +5 -0
- data/spec/d/r/config/environments/development.rb +29 -0
- data/spec/d/r/config/environments/production.rb +80 -0
- data/spec/d/r/config/environments/test.rb +37 -0
- data/spec/d/r/config/initializers/active_admin.rb +225 -0
- data/spec/d/r/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/d/r/config/initializers/devise.rb +252 -0
- data/spec/d/r/config/initializers/devise_async.rb +6 -0
- data/spec/d/r/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/d/r/config/initializers/friendly_id.rb +88 -0
- data/spec/d/r/config/initializers/inflections.rb +16 -0
- data/spec/d/r/config/initializers/mime_types.rb +5 -0
- data/spec/d/r/config/initializers/pageflow.rb +76 -0
- data/spec/d/r/config/initializers/resque.rb +4 -0
- data/spec/d/r/config/initializers/resque_enqueue_after_commit_patch.rb +25 -0
- data/spec/d/r/config/initializers/resque_logger.rb +16 -0
- data/spec/d/r/config/initializers/resque_mailer.rb +4 -0
- data/spec/d/r/config/initializers/secret_token.rb +12 -0
- data/spec/d/r/config/initializers/session_store.rb +3 -0
- data/spec/d/r/config/initializers/wrap_parameters.rb +14 -0
- data/spec/d/r/config/locales/devise.en.yml +59 -0
- data/spec/d/r/config/locales/en.yml +23 -0
- data/spec/d/r/config/routes.rb +59 -0
- data/spec/d/r/config.ru +4 -0
- data/spec/d/r/db/migrate/00000000000000_create_test_hosted_file.rb +7 -0
- data/spec/d/r/db/migrate/00000000000001_create_test_revision_component.rb +10 -0
- data/spec/d/r/db/migrate/20150209101518_create_active_admin_comments.rb +19 -0
- data/spec/d/r/db/migrate/20150209101524_devise_create_users.rb +46 -0
- data/spec/d/r/db/migrate/20150209101530_create_friendly_id_slugs.rb +15 -0
- data/spec/d/r/db/migrate/20150209101540_setup_schema.pageflow.rb +208 -0
- data/spec/d/r/db/migrate/20150209101541_add_attributes_to_users.pageflow.rb +16 -0
- data/spec/d/r/db/migrate/20150209101542_create_themings.pageflow.rb +16 -0
- data/spec/d/r/db/migrate/20150209101543_create_themings_for_existing_accounts.pageflow.rb +27 -0
- data/spec/d/r/db/migrate/20150209101544_change_theme_references_to_theming_references.pageflow.rb +46 -0
- data/spec/d/r/db/migrate/20150209101545_remove_attributes_from_themes.pageflow.rb +11 -0
- data/spec/d/r/db/migrate/20150209101546_create_accounts_themes_join_table.pageflow.rb +9 -0
- data/spec/d/r/db/migrate/20150209101547_move_cname_from_account_to_theming.pageflow.rb +22 -0
- data/spec/d/r/db/migrate/20150209101548_drop_themes.pageflow.rb +15 -0
- data/spec/d/r/db/migrate/20150209101549_add_confirmed_by_to_encoded_files.pageflow.rb +7 -0
- data/spec/d/r/db/migrate/20150209101550_add_home_url_attributes_to_themings_and_revisions.pageflow.rb +10 -0
- data/spec/d/r/db/migrate/20150209101551_create_widgets.pageflow.rb +12 -0
- data/spec/d/r/db/migrate/20150209101552_add_emphasize_chapter_beginning_to_revisions.pageflow.rb +6 -0
- data/spec/d/r/db/migrate/20150209101553_add_emphasize_new_pages_to_revisions.pageflow.rb +6 -0
- data/spec/d/r/db/migrate/20150209101554_add_sharing_image_to_revisions.pageflow.rb +8 -0
- data/spec/d/r/db/schema.rb +316 -0
- data/spec/d/r/db/seeds.rb +30 -0
- data/spec/d/r/lib/assets/.keep +0 -0
- data/spec/d/r/lib/tasks/.keep +0 -0
- data/spec/d/r/lib/tasks/resque.rake +7 -0
- data/spec/d/r/public/404.html +58 -0
- data/spec/d/r/public/422.html +58 -0
- data/spec/d/r/public/500.html +57 -0
- data/spec/d/r/public/favicon.ico +0 -0
- data/spec/d/r/public/javascripts/translations.js +2 -0
- data/spec/d/r/public/robots.txt +5 -0
- data/spec/d/r/vendor/assets/javascripts/.keep +0 -0
- data/spec/d/r/vendor/assets/stylesheets/.keep +0 -0
- data/spec/javascripts/.jshintrc +26 -0
- data/spec/javascripts/pageflow/sitemap/editor/controllers/selection_navigator_spec.js +52 -0
- data/spec/javascripts/pageflow/sitemap/editor/d3/layout/collision_spec.js +99 -0
- data/spec/javascripts/pageflow/sitemap/editor/d3/layout/dragging_decorator_spec.js +114 -0
- data/spec/javascripts/pageflow/sitemap/editor/d3/layout/grid_spec.js +183 -0
- data/spec/javascripts/pageflow/sitemap/editor/d3/layout_spec.js +31 -0
- data/spec/javascripts/pageflow/sitemap/editor/d3/view_model_spec.js +56 -0
- data/spec/javascripts/pageflow/sitemap/editor/models/selection_spec.js +62 -0
- data/spec/javascripts/pageflow/sitemap/scroll_navigator_spec.js +5 -0
- data/spec/javascripts/spec_helper.js +13 -0
- data/spec/javascripts/support/factories.js +81 -0
- data/spec/teaspoon_env.rb +182 -0
- data/vendor/assets/javascripts/d3.v3.js +9215 -0
- metadata +379 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
pageflow.sitemap.layout.Grid = function(chaptersGroupedByStorylines, pagesGroupedByChapters, options) {
|
2
|
+
var positions = {};
|
3
|
+
var chapterSizes = {};
|
4
|
+
var heights = {};
|
5
|
+
var size = {x: 0, y: 0};
|
6
|
+
|
7
|
+
var laneWidth = this.laneWidth = options.pageWidth + 2 * options.pageMarginWidth;
|
8
|
+
var rowHeight = this.rowHeight = options.pageHeight + 2 * options.pageMarginHeight;
|
9
|
+
|
10
|
+
this.chaptersGroupedByStorylines = chaptersGroupedByStorylines;
|
11
|
+
this.pagesGroupedByChapters = pagesGroupedByChapters;
|
12
|
+
this.size = size;
|
13
|
+
|
14
|
+
this.position = function(target) {
|
15
|
+
return positions[target.cid];
|
16
|
+
};
|
17
|
+
|
18
|
+
this.linkSource = function(page) {
|
19
|
+
return {
|
20
|
+
x: this.position(page).x,
|
21
|
+
y: this.position(page).y,
|
22
|
+
width: options.pageWidth,
|
23
|
+
height: heights[page.cid] || options.pageHeight
|
24
|
+
};
|
25
|
+
};
|
26
|
+
|
27
|
+
this.linkTarget = function(page, link) {
|
28
|
+
return this.linkSource(page);
|
29
|
+
};
|
30
|
+
|
31
|
+
this.chapterHeight = function(chapter) {
|
32
|
+
return heights[chapter.cid];
|
33
|
+
};
|
34
|
+
|
35
|
+
this.height = function(target) {
|
36
|
+
if (!heights[target.cid]) {
|
37
|
+
debugger;
|
38
|
+
}
|
39
|
+
|
40
|
+
return heights[target.cid];
|
41
|
+
};
|
42
|
+
|
43
|
+
this.isAbovePage = function(page, position) {
|
44
|
+
var pagePosition = this.position(page);
|
45
|
+
|
46
|
+
return (Math.abs(position.x - pagePosition.x) < laneWidth / 2 &&
|
47
|
+
Math.abs(position.y - pagePosition.y) <= rowHeight / 2 &&
|
48
|
+
position.y < pagePosition.y + rowHeight / 2);
|
49
|
+
};
|
50
|
+
|
51
|
+
this.isAboveChapter = function(chapter, position) {
|
52
|
+
var chapterPosition = this.position(chapter);
|
53
|
+
|
54
|
+
return (Math.abs(position.x - chapterPosition.x) < laneWidth / 2 &&
|
55
|
+
Math.abs(position.y - chapterPosition.y) <= rowHeight / 2 &&
|
56
|
+
position.y < chapterPosition.y + rowHeight / 2);
|
57
|
+
};
|
58
|
+
|
59
|
+
this.pointInsidePage = function(page, position) {
|
60
|
+
var pagePosition = this.position(page);
|
61
|
+
|
62
|
+
return (Math.abs(position.x - pagePosition.x) <= (options.pageWidth + options.pageMarginWidth) / 2 &&
|
63
|
+
Math.abs(position.y - pagePosition.y) <= (options.pageHeight + options.pageMarginHeight) / 2);
|
64
|
+
};
|
65
|
+
|
66
|
+
this.pointInsideChapter = function(chapter, position) {
|
67
|
+
var chapterPosition = this.position(chapter);
|
68
|
+
var chapterHeight = this.chapterHeight(chapter);
|
69
|
+
|
70
|
+
return (Math.abs(position.x - chapterPosition.x) < laneWidth / 2 &&
|
71
|
+
position.y >= chapterPosition.y - rowHeight / 2 &&
|
72
|
+
position.y < chapterPosition.y + chapterHeight);
|
73
|
+
};
|
74
|
+
|
75
|
+
this.pointInsideStoryline = function(storyline, position) {
|
76
|
+
var storylinePosition = this.position(storyline);
|
77
|
+
var height = this.height(storyline);
|
78
|
+
|
79
|
+
return (Math.abs(position.x - storylinePosition.x) < laneWidth / 2 &&
|
80
|
+
position.y >= storylinePosition.y - rowHeight * 1.5 &&
|
81
|
+
position.y < storylinePosition.y + height);
|
82
|
+
};
|
83
|
+
|
84
|
+
this.isBelowChapter = function(chapter, position) {
|
85
|
+
var chapterPosition = this.position(chapter);
|
86
|
+
var chapterBottom =
|
87
|
+
this.position(chapter).y +
|
88
|
+
this.chapterHeight(chapter) +
|
89
|
+
2 * options.pageMarginHeight;
|
90
|
+
|
91
|
+
return (Math.abs(position.x - chapterPosition.x) < laneWidth / 2 &&
|
92
|
+
Math.abs(position.y - chapterBottom) <= rowHeight / 2 &&
|
93
|
+
position.y < chapterBottom + rowHeight / 2);
|
94
|
+
};
|
95
|
+
|
96
|
+
this.isBelowStoryline = function(storyline, position) {
|
97
|
+
var storylinePosition = this.position(storyline);
|
98
|
+
var storylineBottom =
|
99
|
+
this.position(storyline).y +
|
100
|
+
this.height(storyline) +
|
101
|
+
2 * options.pageMarginHeight;
|
102
|
+
|
103
|
+
return (Math.abs(position.x - storylinePosition.x) < laneWidth / 2 &&
|
104
|
+
Math.abs(position.y - storylineBottom) <= rowHeight / 2 &&
|
105
|
+
position.y < storylineBottom + rowHeight / 2);
|
106
|
+
};
|
107
|
+
|
108
|
+
this.laneAndRowFromPoint = function(position) {
|
109
|
+
return {
|
110
|
+
lane: Math.round(position.x / laneWidth),
|
111
|
+
row: Math.round(position.y / rowHeight)
|
112
|
+
};
|
113
|
+
};
|
114
|
+
|
115
|
+
this.freeGridCellFromPoint = function(position) {
|
116
|
+
if (!this.storylineFromPoint(position) &&
|
117
|
+
!this.chapterFromPoint(position) &&
|
118
|
+
!this.pageFromPoint(position)) {
|
119
|
+
|
120
|
+
return this.gridCellFromPoint(position);
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
this.gridCellFromPoint = function(position) {
|
125
|
+
var laneAndRow = this.laneAndRowFromPoint(position);
|
126
|
+
|
127
|
+
if (laneAndRow.lane >= 0 && laneAndRow.row >= 0) {
|
128
|
+
return {
|
129
|
+
laneAndRow: laneAndRow,
|
130
|
+
x: laneAndRow.lane * laneWidth,
|
131
|
+
y: laneAndRow.row * rowHeight,
|
132
|
+
width: options.pageWidth,
|
133
|
+
height: options.pageHeight
|
134
|
+
};
|
135
|
+
}
|
136
|
+
};
|
137
|
+
|
138
|
+
this.storylineFromPoint = function(position) {
|
139
|
+
var that = this;
|
140
|
+
|
141
|
+
return _(chaptersGroupedByStorylines).reduce(function(result, group) {
|
142
|
+
return result || (group.storyline &&
|
143
|
+
that.pointInsideStoryline(group.storyline, position));
|
144
|
+
}, null);
|
145
|
+
};
|
146
|
+
|
147
|
+
this.chapterFromPoint = function(position) {
|
148
|
+
var that = this;
|
149
|
+
|
150
|
+
return _(pagesGroupedByChapters).reduce(function(result, group) {
|
151
|
+
return result || (group.chapter &&
|
152
|
+
that.pointInsideChapter(group.chapter, position));
|
153
|
+
}, null);
|
154
|
+
};
|
155
|
+
|
156
|
+
this.pageFromPoint = function(position) {
|
157
|
+
var that = this;
|
158
|
+
|
159
|
+
return _(pagesGroupedByChapters).reduce(function(result, group) {
|
160
|
+
return result || _(group.pages).find(function(page) {
|
161
|
+
return that.pointInsidePage(page, position);
|
162
|
+
});
|
163
|
+
}, null);
|
164
|
+
};
|
165
|
+
|
166
|
+
this.isLegal = function() {
|
167
|
+
};
|
168
|
+
|
169
|
+
_.each(pagesGroupedByChapters, function(group) {
|
170
|
+
var chapter = group.chapter;
|
171
|
+
|
172
|
+
if (chapter) {
|
173
|
+
var chapterSize = Math.max(1, group.pages.length);
|
174
|
+
chapterSizes[chapter.cid] = chapterSize + 0.5;
|
175
|
+
heights[chapter.cid] = chapterSize * rowHeight - 2 * options.pageMarginHeight;
|
176
|
+
}
|
177
|
+
});
|
178
|
+
|
179
|
+
_.each(chaptersGroupedByStorylines, function(group) {
|
180
|
+
var storyline = group.storyline;
|
181
|
+
|
182
|
+
if (storyline) {
|
183
|
+
positions[storyline.cid] = {
|
184
|
+
x: lane(storyline) * laneWidth,
|
185
|
+
y: row(storyline) * rowHeight
|
186
|
+
};
|
187
|
+
|
188
|
+
var storylineSize = _.reduce(group.chapters, function(offset, chapter) {
|
189
|
+
var chapterSize = chapterSizes[chapter.cid];
|
190
|
+
|
191
|
+
var storylineLane = lane(storyline);
|
192
|
+
var storylineRow = row(storyline) + offset;
|
193
|
+
|
194
|
+
positions[chapter.cid] = {
|
195
|
+
_lane: storylineLane,
|
196
|
+
_row: storylineRow,
|
197
|
+
x: storylineLane * laneWidth,
|
198
|
+
y: storylineRow * rowHeight
|
199
|
+
};
|
200
|
+
|
201
|
+
return offset + chapterSize;
|
202
|
+
}, 0);
|
203
|
+
|
204
|
+
heights[storyline.cid] = Math.max(1, storylineSize) * rowHeight;
|
205
|
+
|
206
|
+
if (!heights[storyline.cid]) {
|
207
|
+
debugger;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
});
|
211
|
+
|
212
|
+
_.each(pagesGroupedByChapters, function(group) {
|
213
|
+
var chapter = group.chapter;
|
214
|
+
|
215
|
+
if (chapter && positions[chapter.cid]) {
|
216
|
+
var chapterLane = positions[chapter.cid]._lane;
|
217
|
+
var chapterRow = positions[chapter.cid]._row;
|
218
|
+
|
219
|
+
_.each(group.pages, function(page, index) {
|
220
|
+
positions[page.cid] = {
|
221
|
+
x: chapterLane * laneWidth,
|
222
|
+
y: (chapterRow + index) * rowHeight
|
223
|
+
};
|
224
|
+
|
225
|
+
size.x = Math.max(size.x, positions[page.cid].x + laneWidth);
|
226
|
+
size.y = Math.max(size.y, positions[page.cid].y + rowHeight);
|
227
|
+
});
|
228
|
+
}
|
229
|
+
});
|
230
|
+
|
231
|
+
function lane(storyline) {
|
232
|
+
return storyline.configuration.get('lane') || 0;
|
233
|
+
}
|
234
|
+
|
235
|
+
function row(storyline) {
|
236
|
+
return storyline.configuration.get('row') || 0;
|
237
|
+
}
|
238
|
+
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
pageflow.sitemap.layout.LinkDraggingDecorator = function(selection, layout, options) {
|
2
|
+
var decorator = function() {
|
3
|
+
var targetPage, targetChapter;
|
4
|
+
|
5
|
+
if (options.dragPosition) {
|
6
|
+
targetPage = layout.pageFromPoint(options.dragPosition);
|
7
|
+
|
8
|
+
this.chapterPlaceholder = layout.freeGridCellFromPoint(options.dragPosition);
|
9
|
+
}
|
10
|
+
|
11
|
+
this.linkTarget = function(page, link) {
|
12
|
+
if (selection.contains(link) && options.dragPosition) {
|
13
|
+
if (targetPage) {
|
14
|
+
return layout.linkTarget(targetPage, link);
|
15
|
+
}
|
16
|
+
|
17
|
+
if (this.chapterPlaceholder) {
|
18
|
+
return this.chapterPlaceholder;
|
19
|
+
}
|
20
|
+
|
21
|
+
return {
|
22
|
+
x: options.dragPosition.x,
|
23
|
+
y: options.dragPosition.y,
|
24
|
+
width: 0,
|
25
|
+
height: 0
|
26
|
+
};
|
27
|
+
}
|
28
|
+
else {
|
29
|
+
return layout.linkTarget(page, link);
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
this.isDragging = function(target) {
|
34
|
+
return (options.dragPosition && selection.contains(target)) ||
|
35
|
+
layout.isDragging(target);
|
36
|
+
};
|
37
|
+
|
38
|
+
};
|
39
|
+
|
40
|
+
decorator.prototype = layout;
|
41
|
+
return new decorator();
|
42
|
+
};
|
@@ -0,0 +1,94 @@
|
|
1
|
+
//= require_self
|
2
|
+
//= require ./layout/grid
|
3
|
+
//= require ./layout/dragging_decorator
|
4
|
+
//= require ./layout/link_dragging_decorator
|
5
|
+
//= require ./layout/collision
|
6
|
+
|
7
|
+
(function() {
|
8
|
+
var s = pageflow.sitemap;
|
9
|
+
|
10
|
+
s.layout = {
|
11
|
+
defaultGrid: {
|
12
|
+
pageWidth: 125,
|
13
|
+
pageHeight: 70,
|
14
|
+
pageMarginWidth: 30,
|
15
|
+
pageMarginHeight: 12
|
16
|
+
},
|
17
|
+
|
18
|
+
create: function(entry, selection, options) {
|
19
|
+
options = _.extend({
|
20
|
+
grid: this.defaultGrid
|
21
|
+
}, options || {});
|
22
|
+
|
23
|
+
// We begin by layouting chapters and pages in a grid.
|
24
|
+
|
25
|
+
var originalLayout =
|
26
|
+
new s.layout.Grid(chaptersGroupedByStorylines(entry),
|
27
|
+
pagesGroupedByChapters(entry),
|
28
|
+
options.grid);
|
29
|
+
|
30
|
+
// Then we create a layout in which the selected pages are
|
31
|
+
// translated by the dragDelta.
|
32
|
+
|
33
|
+
var draggingLayout =
|
34
|
+
new s.layout.DraggingDecorator(selection,
|
35
|
+
originalLayout,
|
36
|
+
originalLayout,
|
37
|
+
{delta: options.dragDelta});
|
38
|
+
// When dragging pages, the reset of the layout collapses as if
|
39
|
+
// the dragged pages were removed. This is the layout we want to
|
40
|
+
// consider when we check collision with dragged pages.
|
41
|
+
|
42
|
+
var collapsedLayout =
|
43
|
+
new s.layout.Grid(draggingLayout.nonDraggedChaptersGroupedByStorylines,
|
44
|
+
draggingLayout.nonDraggedPagesGroupedByChapters,
|
45
|
+
options.grid);
|
46
|
+
|
47
|
+
// Group pages as if they already had been dropped into a target
|
48
|
+
// new chapters. This allows us to calculate a grid layout with
|
49
|
+
// free spaces where pages would be dropped.
|
50
|
+
|
51
|
+
var collision =
|
52
|
+
new s.layout.Collision(draggingLayout, collapsedLayout);
|
53
|
+
|
54
|
+
var spacingLayout =
|
55
|
+
new s.layout.Grid(collision.chaptersGroupedByDragTargetStorylines(),
|
56
|
+
collision.pagesGroupedByDragTargetChapters(),
|
57
|
+
options.grid);
|
58
|
+
|
59
|
+
// The final layout that we want to draw is split into two
|
60
|
+
// parts: For the selected pages, we want to use the position
|
61
|
+
// from the original layout translated by the dragDelta. For all
|
62
|
+
// other pages we want to use the positions from the spacing
|
63
|
+
// layout which already contains placeholder positions for the
|
64
|
+
// dragged pages.
|
65
|
+
|
66
|
+
var layout = new s.layout.DraggingDecorator(selection,
|
67
|
+
spacingLayout,
|
68
|
+
originalLayout,
|
69
|
+
{delta: options.dragDelta});
|
70
|
+
|
71
|
+
return new s.layout.LinkDraggingDecorator(selection,
|
72
|
+
layout,
|
73
|
+
{dragPosition: options.dragPosition});
|
74
|
+
}
|
75
|
+
};
|
76
|
+
|
77
|
+
function chaptersGroupedByStorylines(entry) {
|
78
|
+
return entry.storylines.map(function(storyline) {
|
79
|
+
return {
|
80
|
+
storyline: storyline,
|
81
|
+
chapters: storyline.chapters.toArray()
|
82
|
+
};
|
83
|
+
});
|
84
|
+
}
|
85
|
+
|
86
|
+
function pagesGroupedByChapters(entry) {
|
87
|
+
return entry.chapters.map(function(chapter) {
|
88
|
+
return {
|
89
|
+
chapter: chapter,
|
90
|
+
pages: chapter.pages.toArray()
|
91
|
+
};
|
92
|
+
});
|
93
|
+
}
|
94
|
+
}());
|
@@ -0,0 +1,25 @@
|
|
1
|
+
/*global options*/
|
2
|
+
window.options = sitemap.settings = {
|
3
|
+
margin: {
|
4
|
+
top: 60,
|
5
|
+
right: 60,
|
6
|
+
bottom: 60,
|
7
|
+
left: 60
|
8
|
+
},
|
9
|
+
page: {
|
10
|
+
height: 70,
|
11
|
+
width: 125,
|
12
|
+
verticalMargin: 30,
|
13
|
+
horizontalMargin: 30
|
14
|
+
},
|
15
|
+
|
16
|
+
arrowSize: 8,
|
17
|
+
|
18
|
+
radius: 20,
|
19
|
+
duration: 400,
|
20
|
+
|
21
|
+
panSpeed: 200,
|
22
|
+
panBoundary: 20 // Within 20px from edges will pan when dragging.
|
23
|
+
};
|
24
|
+
|
25
|
+
options.boxHeight = options.page.width + options.page.verticalMargin;
|
@@ -0,0 +1,36 @@
|
|
1
|
+
pageflow.sitemap.followPath = function(d) {
|
2
|
+
var points = sitemap.followPath.points(d);
|
3
|
+
|
4
|
+
var p = [points.start, points.p1, points.p2, points.end].map(function(d) {
|
5
|
+
return [d.x, d.y];
|
6
|
+
});
|
7
|
+
|
8
|
+
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
|
9
|
+
};
|
10
|
+
|
11
|
+
pageflow.sitemap.followPath.points = function(d) {
|
12
|
+
var start, p1, p2, end;
|
13
|
+
var options = pageflow.sitemap.settings;
|
14
|
+
|
15
|
+
start = {
|
16
|
+
x: d.source.x,
|
17
|
+
y: d.source.y + options.page.width / 2
|
18
|
+
};
|
19
|
+
p1 = start;
|
20
|
+
|
21
|
+
p2 = {
|
22
|
+
x: d.target.x,
|
23
|
+
y: d.target.y - options.page.width / 2 - options.arrowSize - 20
|
24
|
+
};
|
25
|
+
end = {
|
26
|
+
x: d.target.x,
|
27
|
+
y: d.target.y - options.page.width / 2 - options.arrowSize
|
28
|
+
};
|
29
|
+
|
30
|
+
return {
|
31
|
+
start: start,
|
32
|
+
p1: p1,
|
33
|
+
p2: p2,
|
34
|
+
end: end
|
35
|
+
};
|
36
|
+
};
|
@@ -0,0 +1,64 @@
|
|
1
|
+
/*global options, sitemap*/
|
2
|
+
|
3
|
+
// path generator to be used in d3 attrib function for path element
|
4
|
+
// path.attr('d', sitemap.linkpath);
|
5
|
+
sitemap.linkpath = function(d) {
|
6
|
+
var points = sitemap.linkpath.points(d);
|
7
|
+
|
8
|
+
var p = [points.start, points.p1, points.p2, points.end].map(function(d) {
|
9
|
+
return [d.x, d.y];
|
10
|
+
});
|
11
|
+
|
12
|
+
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
|
13
|
+
};
|
14
|
+
|
15
|
+
sitemap.linkpath.points = function(d) {
|
16
|
+
var deltaX = d.source.x - d.target.x;
|
17
|
+
var deltaY = d.source.y - d.target.y;
|
18
|
+
|
19
|
+
var start = { x: d.source.x, y: d.source.y + 5},
|
20
|
+
p1 = { x: d.source.x, y: d.source.y + 5},
|
21
|
+
p2 = { x: d.target.x, y: d.target.y - 5},
|
22
|
+
end = { x: d.target.x, y: d.target.y - 5};
|
23
|
+
|
24
|
+
var horizontalMargin = options.page.horizontalMargin * 2;
|
25
|
+
|
26
|
+
var offsetStart = d.source.width / 2,
|
27
|
+
offsetEnd = d.target.width / 2 + options.arrowSize;
|
28
|
+
|
29
|
+
// start of path
|
30
|
+
if (deltaX > options.page.width) {
|
31
|
+
// path from left to right
|
32
|
+
start.x -= offsetStart;
|
33
|
+
p1.x -= offsetStart + horizontalMargin;
|
34
|
+
|
35
|
+
}
|
36
|
+
else {
|
37
|
+
// path from right to left
|
38
|
+
start.x += offsetStart;
|
39
|
+
p1.x += offsetStart + horizontalMargin;
|
40
|
+
}
|
41
|
+
|
42
|
+
if (deltaX === 0 && deltaY === 0) {
|
43
|
+
p1 = p2 = end = start;
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
if (deltaX < -options.page.width) {
|
47
|
+
// path from right to left
|
48
|
+
end.x -= offsetEnd;
|
49
|
+
p2.x -= offsetEnd + horizontalMargin;
|
50
|
+
}
|
51
|
+
else {
|
52
|
+
// path from left to right
|
53
|
+
p2.x += offsetEnd + horizontalMargin;
|
54
|
+
end.x += offsetEnd;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
return {
|
59
|
+
start: start,
|
60
|
+
p1: p1,
|
61
|
+
p2: p2,
|
62
|
+
end: end
|
63
|
+
};
|
64
|
+
};
|
@@ -0,0 +1,49 @@
|
|
1
|
+
pageflow.sitemap.successorPath = function(d) {
|
2
|
+
var points = sitemap.successorPath.points(d);
|
3
|
+
|
4
|
+
var p = [points.start, points.p1, points.p2, points.end].map(function(d) {
|
5
|
+
return [d.x, d.y];
|
6
|
+
});
|
7
|
+
|
8
|
+
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
|
9
|
+
};
|
10
|
+
|
11
|
+
pageflow.sitemap.successorPath.points = function(d) {
|
12
|
+
var deltaX = d.source.x - d.target.x;
|
13
|
+
var deltaY = d.source.y - d.target.y;
|
14
|
+
|
15
|
+
var start = { x: d.source.x, y: d.source.y},
|
16
|
+
p1 = { x: d.source.x, y: d.source.y + 40},
|
17
|
+
p2 = { x: d.target.x, y: d.target.y - 40},
|
18
|
+
end = { x: d.target.x, y: d.target.y};
|
19
|
+
|
20
|
+
var offsetStart = d.source.height - pageflow.sitemap.settings.page.height / 2 - 25,
|
21
|
+
offsetEnd = d.target.height / 2 + pageflow.sitemap.settings.arrowSize;
|
22
|
+
|
23
|
+
start.y += offsetStart;
|
24
|
+
p1.y += offsetStart;
|
25
|
+
|
26
|
+
if (deltaX === 0 && deltaY === 0) {
|
27
|
+
p1 = p2 = end = start;
|
28
|
+
}
|
29
|
+
else {
|
30
|
+
end.y -= offsetEnd;
|
31
|
+
p2.y -= offsetEnd;
|
32
|
+
|
33
|
+
if (deltaX > 0) {
|
34
|
+
end.x += 15;
|
35
|
+
p2.x += 15;
|
36
|
+
}
|
37
|
+
else {
|
38
|
+
end.x -= 15;
|
39
|
+
p2.x -= 15;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
return {
|
44
|
+
start: start,
|
45
|
+
p1: p1,
|
46
|
+
p2: p2,
|
47
|
+
end: end
|
48
|
+
};
|
49
|
+
};
|
@@ -0,0 +1,33 @@
|
|
1
|
+
pageflow.sitemap.utils = {
|
2
|
+
size: function(selection, w, h) {
|
3
|
+
selection
|
4
|
+
.attr('width', w)
|
5
|
+
.attr('height', h);
|
6
|
+
},
|
7
|
+
|
8
|
+
translate: function(x, y) {
|
9
|
+
return 'translate(' + x + ',' + y + ')';
|
10
|
+
},
|
11
|
+
|
12
|
+
fn: {
|
13
|
+
d: function(property) {
|
14
|
+
return function(d) {
|
15
|
+
return d[property];
|
16
|
+
};
|
17
|
+
},
|
18
|
+
|
19
|
+
translate: function(x, y) {
|
20
|
+
return function(d) {
|
21
|
+
return 'translate(' + d[x] + ',' + d[y] + ')';
|
22
|
+
};
|
23
|
+
},
|
24
|
+
|
25
|
+
trigger: function(fn) {
|
26
|
+
return function(d) {
|
27
|
+
if (typeof fn === 'function') {
|
28
|
+
fn.apply(this, arguments);
|
29
|
+
}
|
30
|
+
};
|
31
|
+
}
|
32
|
+
}
|
33
|
+
};
|