diff --git a/css/app.css b/css/app.css
index 256b7c91b..3ac71d399 100644
--- a/css/app.css
+++ b/css/app.css
@@ -1534,6 +1534,13 @@ input[type=number] {
border-bottom: 0;
border-radius: 0 0 4px 0;
}
+
+/* Restrictions editor */
+
+.form-field-restrictions .preset-input-wrap {
+ height: 300px;
+}
+
/* combobox dropdown */
div.combobox {
diff --git a/data/presets.yaml b/data/presets.yaml
index 1c661f7e4..7956ed495 100644
--- a/data/presets.yaml
+++ b/data/presets.yaml
@@ -296,6 +296,8 @@ en:
taoist: Taoist
restriction:
label: Type
+ restrictions:
+ label: Turn Restrictions
route:
label: Type
route_master:
diff --git a/data/presets/fields.json b/data/presets/fields.json
index c25b151e9..af125a0bb 100644
--- a/data/presets/fields.json
+++ b/data/presets/fields.json
@@ -721,6 +721,15 @@
"type": "combo",
"label": "Type"
},
+ "restrictions": {
+ "type": "restrictions",
+ "geometry": "vertex",
+ "icon": "restrictions",
+ "reference": {
+ "rtype": "restriction"
+ },
+ "label": "Turn Restrictions"
+ },
"route": {
"key": "route",
"type": "combo",
diff --git a/data/presets/fields/restrictions.json b/data/presets/fields/restrictions.json
new file mode 100644
index 000000000..4873601f9
--- /dev/null
+++ b/data/presets/fields/restrictions.json
@@ -0,0 +1,9 @@
+{
+ "type": "restrictions",
+ "geometry": "vertex",
+ "icon": "restrictions",
+ "reference": {
+ "rtype": "restriction"
+ },
+ "label": "Turn Restrictions"
+}
diff --git a/data/presets/presets.json b/data/presets/presets.json
index 407d0418b..13e4dc6e5 100644
--- a/data/presets/presets.json
+++ b/data/presets/presets.json
@@ -4245,6 +4245,9 @@
"tags": {
"highway": "traffic_signals"
},
+ "fields": [
+ "restrictions"
+ ],
"terms": [
"light",
"stoplight",
diff --git a/data/presets/presets/highway/traffic_signals.json b/data/presets/presets/highway/traffic_signals.json
index 62e5d60e8..7f3fd4157 100644
--- a/data/presets/presets/highway/traffic_signals.json
+++ b/data/presets/presets/highway/traffic_signals.json
@@ -5,6 +5,9 @@
"tags": {
"highway": "traffic_signals"
},
+ "fields": [
+ "restrictions"
+ ],
"terms": [
"light",
"stoplight",
diff --git a/data/presets/schema/field.json b/data/presets/schema/field.json
index 12a45ee5f..3cc081660 100644
--- a/data/presets/schema/field.json
+++ b/data/presets/schema/field.json
@@ -63,7 +63,8 @@
"textarea",
"localized",
"wikipedia",
- "typeCombo"
+ "typeCombo",
+ "restrictions"
],
"required": true
},
diff --git a/dist/locales/en.json b/dist/locales/en.json
index 8fff93692..64d57639d 100644
--- a/dist/locales/en.json
+++ b/dist/locales/en.json
@@ -825,6 +825,9 @@
"restriction": {
"label": "Type"
},
+ "restrictions": {
+ "label": "Turn Restrictions"
+ },
"route": {
"label": "Type"
},
diff --git a/index.html b/index.html
index 4fd3ffbaf..aee983d3b 100644
--- a/index.html
+++ b/index.html
@@ -120,6 +120,7 @@
+
diff --git a/js/id/ui/preset/restrictions.js b/js/id/ui/preset/restrictions.js
new file mode 100644
index 000000000..a6d12953a
--- /dev/null
+++ b/js/id/ui/preset/restrictions.js
@@ -0,0 +1,71 @@
+iD.ui.preset.restrictions = function(field, context) {
+ var event = d3.dispatch('change'),
+ entity;
+
+ function restrictions(selection) {
+ var wrap = selection.selectAll('.preset-input-wrap')
+ .data([0]);
+
+ // Enter
+
+ var enter = wrap.enter().append('div')
+ .attr('class', 'preset-input-wrap');
+
+ enter.append('svg')
+ .call(iD.svg.Surface(context))
+ .call(iD.behavior.Hover(context));
+
+ var d = wrap.dimensions(),
+ c = [d[0] / 2, d[1] / 2],
+ z = 21;
+
+ var projection = iD.geo.RawMercator()
+ .scale(256 * Math.pow(2, z) / (2 * Math.PI));
+
+ var s = projection(entity ? entity.loc : [0, 0]);
+
+ projection
+ .translate([c[0] - s[0], c[1] - s[1]])
+ .clipExtent([[0, 0], d]);
+
+ var surface = wrap.selectAll('svg'),
+ filter = function () { return true; },
+ extent = iD.geo.Extent(),
+ entities = [],
+ graph = context.graph(),
+ lines = iD.svg.Lines(projection, context),
+ vertices = iD.svg.Vertices(projection, context);
+
+ if (entity) {
+ entities = graph.parentWays(entity).filter(function (parent) {
+ return parent.type === 'way' && parent.tags.highway && !parent.isArea();
+ });
+
+ entities.push(entity);
+ }
+
+ surface
+ .call(vertices, graph, entities, filter, extent, z)
+ .call(lines, graph, entities, filter);
+
+ context.history()
+ .on('change.restrictions', render);
+
+ d3.select(window)
+ .on('resize.restrictions', render);
+
+ function render() {
+ restrictions(selection);
+ }
+ }
+
+ restrictions.tags = function() {};
+
+ restrictions.entity = function(_) {
+ entity = _;
+ };
+
+ restrictions.focus = function() {};
+
+ return d3.rebind(restrictions, event, 'on');
+};