├── README.md
├── jquery.subwayMap-0.5.3.js
└── subwayMap.htm
/README.md:
--------------------------------------------------------------------------------
1 | # subwayMap
2 | A jquery plugin to render data as a subway map visualization
3 |
4 | 
5 |
6 | # Usage
7 |
8 | Read the [step-by-step guide](https://kalyani.com/blog/2010/10/08/subway-map-visualization-jquery-plugin/) on the author blog
9 |
--------------------------------------------------------------------------------
/jquery.subwayMap-0.5.3.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (c) 2010 Nik Kalyani nik@kalyani.com http://www.kalyani.com
4 |
5 | Modified work Copyright (c) 2016 Jon Burrows subwaymap@jonburrows.co.uk https://jonburrows.co.uk
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 |
25 | */
26 |
27 | (function ($) {
28 |
29 | var plugin = {
30 |
31 | defaults: {
32 | debug: false,
33 | grid: false
34 | },
35 |
36 | options: {
37 | },
38 |
39 | identity: function (type) {
40 | if (type === undefined) type = "name";
41 |
42 | switch (type.toLowerCase()) {
43 | case "version": return "1.0.0"; break;
44 | default: return "subwayMap Plugin"; break;
45 | }
46 | },
47 | _debug: function (s) {
48 | if (this.options.debug)
49 | this._log(s);
50 | },
51 | _log: function () {
52 | if (window.console && window.console.log)
53 | window.console.log('[subwayMap] ' + Array.prototype.join.call(arguments, ' '));
54 | },
55 | _supportsCanvas: function () {
56 | var canvas = $("");
57 | if (canvas[0].getContext)
58 | return true;
59 | else
60 | return false;
61 | },
62 | _getCanvasLayer: function (el, overlay) {
63 | this.layer++;
64 | var canvas = $("");
65 | el.append(canvas);
66 | return (canvas[0].getContext("2d"));
67 | },
68 | _render: function (el) {
69 |
70 | this.layer = -1;
71 | var rows = el.attr("data-rows");
72 | if (rows === undefined)
73 | rows = 10;
74 | else
75 | rows = parseInt(rows);
76 |
77 | var columns = el.attr("data-columns");
78 | if (columns === undefined)
79 | columns = 10;
80 | else
81 | columns = parseInt(columns);
82 |
83 | var scale = el.attr("data-cellSize");
84 | if (scale === undefined)
85 | scale = 100;
86 | else
87 | scale = parseInt(scale);
88 |
89 | var lineWidth = el.attr("data-lineWidth");
90 | if (lineWidth === undefined)
91 | lineWidth = 10;
92 | else
93 | lineWidth = parseInt(lineWidth);
94 |
95 | var textClass = el.attr("data-textClass");
96 | if (textClass === undefined) textClass = "";
97 |
98 | var grid = el.attr("data-grid");
99 | if ((grid === undefined) || (grid.toLowerCase() == "false"))
100 | grid = false;
101 | else
102 | grid = true;
103 |
104 | var legendId = el.attr("data-legendId");
105 | if (legendId === undefined) legendId = "";
106 |
107 | var gridNumbers = el.attr("data-gridNumbers");
108 | if ((gridNumbers === undefined) || (gridNumbers.toLowerCase() == "false"))
109 | gridNumbers = false;
110 | else
111 | gridNumbers = true;
112 |
113 | var reverseMarkers = el.attr("data-reverseMarkers");
114 | if ((reverseMarkers === undefined) || (reverseMarkers.toLowerCase() == "false"))
115 | reverseMarkers = false;
116 | else
117 | reverseMarkers = true;
118 |
119 |
120 | this.options.pixelWidth = columns * scale;
121 | this.options.pixelHeight = rows * scale;
122 |
123 | //el.css("width", this.options.pixelWidth);
124 | //el.css("height", this.options.pixelHeight);
125 | var self = this;
126 | var lineLabels = [];
127 | var supportsCanvas = $("")[0].getContext;
128 | if (supportsCanvas) {
129 |
130 | if (grid) this._drawGrid(el, scale, gridNumbers);
131 | $(el).children("ul").each(function (index) {
132 | var ul = $(this);
133 |
134 | var color = $(ul).attr("data-color");
135 | if (color === undefined) color = "#000000";
136 |
137 | var outline = $(ul).attr("data-outline");
138 | if (outline != undefined && ((outline === true) || (outline.toLowerCase() == "true")))
139 | outline = true;
140 | else
141 | outline = false;
142 |
143 | var dotted = $(ul).attr("data-dotted");
144 | if (dotted != undefined && ((dotted === true) || (dotted.toLowerCase() == "true")))
145 | dotted = true;
146 | else
147 | dotted = false;
148 |
149 | var lineTextClass = $(ul).attr("data-textClass");
150 | if (lineTextClass === undefined) lineTextClass = "";
151 |
152 | var shiftCoords = $(ul).attr("data-shiftCoords");
153 | if (shiftCoords === undefined) shiftCoords = "";
154 |
155 | var shiftX = 0.00;
156 | var shiftY = 0.00;
157 | if (shiftCoords.indexOf(",") > -1) {
158 | shiftX = parseInt(shiftCoords.split(",")[0]) * lineWidth/scale;
159 | shiftY = parseInt(shiftCoords.split(",")[1]) * lineWidth/scale;
160 | }
161 |
162 | var lineLabel = $(ul).attr("data-label");
163 | if (lineLabel === undefined)
164 | lineLabel = "Line " + index;
165 |
166 | lineLabels[lineLabels.length] = {label: lineLabel, color: color, outline: outline, dotted: dotted };
167 |
168 | var nodes = [];
169 | $(ul).children("li").each(function () {
170 |
171 | var coords = $(this).attr("data-coords");
172 | if (coords === undefined) coords = "";
173 |
174 | var dir = $(this).attr("data-dir");
175 | if (dir === undefined) dir = "";
176 |
177 | var labelPos = $(this).attr("data-labelPos");
178 | if (labelPos === undefined) labelPos = "s";
179 |
180 | var marker = $(this).attr("data-marker");
181 | if (marker == undefined) marker = "";
182 |
183 | var markerInfo = $(this).attr("data-markerInfo");
184 | if (markerInfo == undefined) markerInfo = "";
185 |
186 | var anchor = $(this).children("a:first-child");
187 | var label = $(this).text();
188 | if (label === undefined) label = "";
189 |
190 | var link = "";
191 | var title = "";
192 | if (anchor != undefined) {
193 | link = $(anchor).attr("href");
194 | if (link === undefined) link = "";
195 | title = $(anchor).attr("title");
196 | if (title === undefined) title = "";
197 | }
198 |
199 | self._debug("Coords=" + coords + "; Dir=" + dir + "; Link=" + link + "; Label=" + label + "; labelPos=" + labelPos + "; Marker=" + marker);
200 |
201 | var x = "";
202 | var y = "";
203 | if (coords.indexOf(",") > -1) {
204 | x = Number(coords.split(",")[0]) + (marker.indexOf("interchange") > -1 ? 0 : shiftX);
205 | y = Number(coords.split(",")[1]) + (marker.indexOf("interchange") > -1 ? 0 : shiftY);
206 | }
207 | nodes[nodes.length] = { x: x, y: y, direction: dir, marker: marker, markerInfo: markerInfo, link: link, title: title, label: label, labelPos: labelPos };
208 | });
209 |
210 | if (nodes.length > 0) {
211 | self._drawLine(el, scale, rows, columns, color, (lineTextClass != "" ? lineTextClass : textClass), lineWidth, nodes, reverseMarkers, dotted);
212 | if (outline === true)
213 | self._drawLine(el, scale, rows, columns, '#FFFFFF', false, lineWidth - 2, nodes, reverseMarkers, dotted);
214 | }
215 |
216 | $(ul).remove();
217 | });
218 |
219 | if ((lineLabels.length > 0) && (legendId != ""))
220 | {
221 | var legend = $("#" + legendId);
222 |
223 | for(var line=0; line