From 39e56f3e6185da66050572585d79903901ffa46a Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Mon, 23 Sep 2013 09:17:35 +0200 Subject: [PATCH 1/7] Add styleMap parsing --- src/ol/parser/kmlparser.js | 82 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/src/ol/parser/kmlparser.js b/src/ol/parser/kmlparser.js index d10945df1b..2b63017708 100644 --- a/src/ol/parser/kmlparser.js +++ b/src/ol/parser/kmlparser.js @@ -172,10 +172,31 @@ ol.parser.KML = function(opt_options) { } } var symbolizers = undefined; - if (goog.isDef(container.styles)) { + if (goog.isDef(container.styleUrl)) { + feature.set('styleUrl', container.styleUrl); + + } else if (goog.isDef(container.styles)) { symbolizers = container.styles[0].symbolizers; + + } else if (goog.isDef(container.styleMaps)) { + var styleMap = container.styleMaps[0]; + + for (var i = 0, ii = styleMap.pairs.length; i < ii; i++) { + var pair = styleMap.pairs[i]; + + if (pair.key === 'normal') { + + if (goog.isDef(pair.styleUrl)) { + feature.set('styleUrl', pair.styleUrl); + + } else if (goog.isDef(pair.styles)) { + symbolizers = pair.styles[0].symbolizers; + } + } + } } - this.applyStyle_(feature, obj['styles'], symbolizers); + + this.applyStyle_(feature, obj['styles'], obj['styleMaps'], symbolizers); obj.features.push(feature); } }, @@ -333,6 +354,35 @@ ol.parser.KML = function(opt_options) { var name = node.nodeName.split(':').pop(); container.attributes[name].push(this.getChildValue(node)); }, + 'StyleMap': function(node, obj) { + if (this.extractStyles === true) { + if (!obj['styleMaps']) { + obj['styleMaps'] = []; + } + var styleMap = {'pairs':[], 'ids': []}; + var id = node.getAttribute('id'); + if (!goog.isNull(id)) { + styleMap['id'] = id; + } + this.readChildNodes(node, styleMap); + obj['styleMaps'].push(styleMap); + } + }, + 'Pair': function(node, obj) { + var pair = {}; + var id = node.getAttribute('id'); + if (!goog.isNull(id)) { + pair['id'] = id; + } + this.readChildNodes(node, pair); + obj['pairs'].push(pair); + }, + 'key': function(node, obj) { + obj.key = this.getChildValue(node); + }, + 'styleUrl': function(node, obj) { + obj.styleUrl = this.getChildValue(node); + }, 'Style': function(node, obj) { if (this.extractStyles === true) { if (!obj['styles']) { @@ -1000,17 +1050,40 @@ ol.parser.KML.prototype.read = function(data, opt_callback) { * @private * @param {ol.Feature} feature The feature to apply the style to. * @param {Array} styles The style list to search in. + * @param {Array} styleMaps The styleMap list to search in. * @param {Array.=} opt_symbolizers Optional symbolizers. */ -ol.parser.KML.prototype.applyStyle_ = function(feature, styles, +ol.parser.KML.prototype.applyStyle_ = function(feature, styles, styleMaps, opt_symbolizers) { var symbolizers = opt_symbolizers; var i, ii; if (feature.get('styleUrl') && feature.getSymbolizers() === null) { var styleUrl = feature.get('styleUrl'); styleUrl = styleUrl.substring(styleUrl.indexOf('#') + 1); + + // look for the styleMap and set in the feature + if (goog.isDef(styleMaps)) { + for (i = 0, ii = styleMaps.length; i < ii; ++i) { + var styleMap = styleMaps[i]; + if (styleMap['id'] === styleUrl) { + for (var j = 0, jj = styleMap.pairs.length; j < jj; j++) { + var pair = styleMap.pairs[j]; + if (pair.key === 'normal') { + if (goog.isDef(pair.styleUrl)) { + styleUrl = pair.styleUrl; + styleUrl = styleUrl.substring(styleUrl.indexOf('#') + 1); + } else if (goog.isDef(pair.styles)) { + symbolizers = pair.styles[0]['symbolizers']; + } + } + } + break; + } + } + } + // look for the style and set in the feature - if (goog.isDef(styles)) { + if (!goog.isDef(symbolizers) && goog.isDef(styles)) { for (i = 0, ii = styles.length; i < ii; ++i) { if (styles[i]['id'] === styleUrl) { symbolizers = styles[i]['symbolizers']; @@ -1018,6 +1091,7 @@ ol.parser.KML.prototype.applyStyle_ = function(feature, styles, } } } + } if (goog.isDef(symbolizers)) { feature.setSymbolizers(symbolizers); From e7222c040c3830681f6cd4333c8ad21a4f5f9124 Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Mon, 23 Sep 2013 14:06:52 +0200 Subject: [PATCH 2/7] Fix styleUrl parsing --- examples/data/kml/lines.kml | 24 ++++++++++++++-------- examples/data/kml/styles.kml | 11 ++++++++++ src/ol/parser/kmlparser.js | 40 +++++++++++++++++------------------- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/examples/data/kml/lines.kml b/examples/data/kml/lines.kml index adc8db6c55..cea9668e7a 100644 --- a/examples/data/kml/lines.kml +++ b/examples/data/kml/lines.kml @@ -262,14 +262,22 @@ -112.2626894973474,36.10149062823369,630 - - Blue Icon - Just another blue icon. - data/kml/styles.kml#blueIcons - - -112.292238941097,36.09520916122063,630 - - + + Blue Icon + Just another blue icon. + data/kml/styles.kml#blueIcons + + -112.292238941097,36.09520916122063,630 + + + + Sun Icon + Just another sun icon. + data/kml/styles.kml#sunIconMap + + -112.292238941097,36.15520916122063,630 + + diff --git a/examples/data/kml/styles.kml b/examples/data/kml/styles.kml index 24350ade44..b362878195 100644 --- a/examples/data/kml/styles.kml +++ b/examples/data/kml/styles.kml @@ -17,5 +17,16 @@ http://kml-samples.googlecode.com/svn/trunk/kml/Style/styles.kml + + + normal + #blueIcons + + + highlight + #blueIcons + + + diff --git a/src/ol/parser/kmlparser.js b/src/ol/parser/kmlparser.js index 2b63017708..b092cfa31f 100644 --- a/src/ol/parser/kmlparser.js +++ b/src/ol/parser/kmlparser.js @@ -148,12 +148,8 @@ ol.parser.KML = function(opt_options) { obj.features.push(feature); } } else if (goog.isDef(container.geometry)) { - var styleUrl = container.properties['styleUrl']; - if (goog.isDef(styleUrl)) { - if (!goog.string.startsWith(styleUrl, '#')) { - obj.links.push({href: styleUrl}); - } - } + this.parseStyleUrl(obj, container.properties['styleUrl']); + feature = new ol.Feature(container.properties); if (!goog.isNull(id)) { feature.setId(id); @@ -172,23 +168,17 @@ ol.parser.KML = function(opt_options) { } } var symbolizers = undefined; - if (goog.isDef(container.styleUrl)) { - feature.set('styleUrl', container.styleUrl); - - } else if (goog.isDef(container.styles)) { + if (goog.isDef(container.styles)) { symbolizers = container.styles[0].symbolizers; } else if (goog.isDef(container.styleMaps)) { var styleMap = container.styleMaps[0]; - for (var i = 0, ii = styleMap.pairs.length; i < ii; i++) { var pair = styleMap.pairs[i]; - if (pair.key === 'normal') { - if (goog.isDef(pair.styleUrl)) { + this.parseStyleUrl(obj, pair.styleUrl); feature.set('styleUrl', pair.styleUrl); - } else if (goog.isDef(pair.styles)) { symbolizers = pair.styles[0].symbolizers; } @@ -377,12 +367,6 @@ ol.parser.KML = function(opt_options) { this.readChildNodes(node, pair); obj['pairs'].push(pair); }, - 'key': function(node, obj) { - obj.key = this.getChildValue(node); - }, - 'styleUrl': function(node, obj) { - obj.styleUrl = this.getChildValue(node); - }, 'Style': function(node, obj) { if (this.extractStyles === true) { if (!obj['styles']) { @@ -960,6 +944,20 @@ ol.parser.KML.prototype.readFeaturesFromObject = }; +/** + * Parse the link contained in styleUrl, if it exists. + * @param {Object} obj The returned object from the parser. + * @param {String} styleUrl The style url to parse. + */ +ol.parser.KML.prototype.parseStyleUrl = function(obj, styleUrl) { + if (goog.isDef(styleUrl)) { + if (!goog.string.startsWith(styleUrl, '#')) { + obj.links.push({href: styleUrl}); + } + } +}; + + /** * @param {Array} deferreds List of deferred instances. * @param {Object} obj The returned object from the parser. @@ -1033,7 +1031,7 @@ ol.parser.KML.prototype.read = function(data, opt_callback) { function(datas) { for (var i = 0, ii = obj.features.length; i < ii; ++i) { var feature = obj.features[i]; - this.applyStyle_(feature, obj['styles']); + this.applyStyle_(feature, obj['styles'], obj['styleMaps']); } opt_callback.call(null, obj); }, function() { From 518658d7de89eea3844fb08fde6ea27aec0501d5 Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Wed, 25 Sep 2013 16:55:50 +0200 Subject: [PATCH 3/7] Add styleMap writer --- src/ol/parser/kmlparser.js | 63 ++++++++++++++++++++++++++------- test/spec/ol/parser/kml.test.js | 25 +++++++++++++ 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/ol/parser/kmlparser.js b/src/ol/parser/kmlparser.js index b092cfa31f..de40598814 100644 --- a/src/ol/parser/kmlparser.js +++ b/src/ol/parser/kmlparser.js @@ -178,15 +178,16 @@ ol.parser.KML = function(opt_options) { if (pair.key === 'normal') { if (goog.isDef(pair.styleUrl)) { this.parseStyleUrl(obj, pair.styleUrl); - feature.set('styleUrl', pair.styleUrl); + feature.set('styleUrl', pair.styleUrl); } else if (goog.isDef(pair.styles)) { - symbolizers = pair.styles[0].symbolizers; + symbolizers = pair.styles[0].symbolizers; } } } } - this.applyStyle_(feature, obj['styles'], obj['styleMaps'], symbolizers); + this.applyStyle_(feature, obj['styles'], obj['styleMaps'], + symbolizers); obj.features.push(feature); } }, @@ -349,7 +350,7 @@ ol.parser.KML = function(opt_options) { if (!obj['styleMaps']) { obj['styleMaps'] = []; } - var styleMap = {'pairs':[], 'ids': []}; + var styleMap = {'pairs': []}; var id = node.getAttribute('id'); if (!goog.isNull(id)) { styleMap['id'] = id; @@ -634,6 +635,11 @@ ol.parser.KML = function(opt_options) { this.writeNode('_style', options.styles[i], null, node); } } + if (goog.isDef(options.styleMaps)) { + for (i = 0, ii = options.styleMaps.length; i < ii; ++i) { + this.writeNode('_styleMap', options.styleMaps[i], null, node); + } + } for (i = 0, ii = options.features.length; i < ii; ++i) { this.writeNode('_feature', options.features[i], null, node); } @@ -652,6 +658,16 @@ ol.parser.KML = function(opt_options) { } return node; }, + '_styleMap': function(styleMap) { + var node = this.createElementNS('StyleMap'); + if (goog.isDef(styleMap.id)) { + this.setAttributeNS(node, null, 'id', styleMap.id); + } + for (var i = 0, ii = styleMap.pairs.length; i < ii; ++i) { + this.writeNode('Pair', styleMap.pairs[i], null, node); + } + return node; + }, '_symbolizer': function(obj) { var symbolizer = obj.symbolizer; if (symbolizer instanceof ol.style.Icon) { @@ -662,6 +678,28 @@ ol.parser.KML = function(opt_options) { return this.writeNode('PolyStyle', obj); } }, + 'Pair': function(pair) { + var node = this.createElementNS('Pair'); + if (goog.isDef(pair.id)) { + this.setAttributeNS(node, null, 'id', pair.id); + } + if (goog.isDef(pair.key)) { + this.writeNode('key', pair.key, null, node); + } + if (goog.isDef(pair.styleUrl)) { + this.writeNode('styleUrl', pair.styleUrl, null, node); + } else if (goog.isDef(pair.styles)) { + for (var i = 0, ii = pair.styles.length; i < ii; ++i) { + this.writeNode('_style', pair.styles[i], null, node); + } + } + return node; + }, + 'key': function(key) { + var node = this.createElementNS('key'); + node.appendChild(this.createTextNode(key)); + return node; + }, 'PolyStyle': function(obj) { /** * In KML, if a PolyStyle has 1 @@ -761,7 +799,7 @@ ol.parser.KML = function(opt_options) { this.writeNode('name', feature, null, node); this.writeNode('description', feature, null, node); if (goog.isDef(feature.get('styleUrl'))) { - this.writeNode('styleUrl', feature, null, node); + this.writeNode('styleUrl', feature.get('styleUrl'), null, node); } else { // inline style var symbolizers = feature.getSymbolizers(); @@ -788,8 +826,7 @@ ol.parser.KML = function(opt_options) { return node; } }, - 'styleUrl': function(feature) { - var styleUrl = feature.get('styleUrl'); + 'styleUrl': function(styleUrl) { var node = this.createElementNS('styleUrl'); node.appendChild(this.createTextNode(styleUrl)); return node; @@ -947,14 +984,14 @@ ol.parser.KML.prototype.readFeaturesFromObject = /** * Parse the link contained in styleUrl, if it exists. * @param {Object} obj The returned object from the parser. - * @param {String} styleUrl The style url to parse. + * @param {string} styleUrl The style url to parse. */ ol.parser.KML.prototype.parseStyleUrl = function(obj, styleUrl) { if (goog.isDef(styleUrl)) { if (!goog.string.startsWith(styleUrl, '#')) { obj.links.push({href: styleUrl}); } - } + } }; @@ -1069,16 +1106,16 @@ ol.parser.KML.prototype.applyStyle_ = function(feature, styles, styleMaps, if (pair.key === 'normal') { if (goog.isDef(pair.styleUrl)) { styleUrl = pair.styleUrl; - styleUrl = styleUrl.substring(styleUrl.indexOf('#') + 1); + styleUrl = styleUrl.substring(styleUrl.indexOf('#') + 1); } else if (goog.isDef(pair.styles)) { - symbolizers = pair.styles[0]['symbolizers']; + symbolizers = pair.styles[0]['symbolizers']; } } } break; } } - } + } // look for the style and set in the feature if (!goog.isDef(symbolizers) && goog.isDef(styles)) { @@ -1089,7 +1126,7 @@ ol.parser.KML.prototype.applyStyle_ = function(feature, styles, styleMaps, } } } - + } if (goog.isDef(symbolizers)) { feature.setSymbolizers(symbolizers); diff --git a/test/spec/ol/parser/kml.test.js b/test/spec/ol/parser/kml.test.js index 3a3d104abb..8d6d678c8d 100644 --- a/test/spec/ol/parser/kml.test.js +++ b/test/spec/ol/parser/kml.test.js @@ -283,6 +283,31 @@ describe('ol.parser.KML', function() { done(); }); }); + + it('handles styleMap (read / write)', function(done) { + var url = 'spec/ol/parser/kml/stylemap.kml'; + afterLoadXml(url, function(xml) { + var p = new ol.parser.KML({extractStyles: true}); + var obj = p.read(xml); + var output = p.write(obj); + expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); + + var symbolizers = obj.features[0].getSymbolizers(); + expect(symbolizers).to.have.length(1); + + var symbolizer = symbolizers[0]; + expect(symbolizer).to.be.a(ol.style.Icon); + + var literal = symbolizer.createLiteral(ol.geom.GeometryType.POINT); + expect(literal).to.be.a(ol.style.IconLiteral); + + var url = 'http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png'; + expect(literal.url).to.eql(url); + expect(literal.width).to.eql(32); + expect(literal.height).to.eql(32); + done(); + }); + }); }); describe('parsing states.kml', function() { From 67a6703e50b62dea4b1d8d836801990998447d8f Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Thu, 26 Sep 2013 09:24:30 +0200 Subject: [PATCH 4/7] Remove space --- test/spec/ol/parser/kml.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/ol/parser/kml.test.js b/test/spec/ol/parser/kml.test.js index 8d6d678c8d..f7dffe3eb9 100644 --- a/test/spec/ol/parser/kml.test.js +++ b/test/spec/ol/parser/kml.test.js @@ -291,7 +291,7 @@ describe('ol.parser.KML', function() { var obj = p.read(xml); var output = p.write(obj); expect(goog.dom.xml.loadXml(output)).to.xmleql(xml); - + var symbolizers = obj.features[0].getSymbolizers(); expect(symbolizers).to.have.length(1); From 5c128abc5d2f3239c55656034e4c3dabd6b40019 Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Thu, 26 Sep 2013 09:50:46 +0200 Subject: [PATCH 5/7] Add kml file for test --- test/spec/ol/parser/kml/stylemap.kml | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/spec/ol/parser/kml/stylemap.kml diff --git a/test/spec/ol/parser/kml/stylemap.kml b/test/spec/ol/parser/kml/stylemap.kml new file mode 100644 index 0000000000..622becbfaa --- /dev/null +++ b/test/spec/ol/parser/kml/stylemap.kml @@ -0,0 +1,29 @@ + + + + + + + normal + #pushpin + + + highlight + #pushpin + + + + Pin on a mountaintop + #pushpinStyleMap + + 170.1435558771009,-43.60505741890396,0 + + + + \ No newline at end of file From 422efbe38ba828b5da84507d9ec7c7f1e520621c Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Thu, 26 Sep 2013 13:11:10 +0200 Subject: [PATCH 6/7] Use quoted properties to fix build failure in advanced mode --- src/ol/parser/kmlparser.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/ol/parser/kmlparser.js b/src/ol/parser/kmlparser.js index de40598814..32abacbfd4 100644 --- a/src/ol/parser/kmlparser.js +++ b/src/ol/parser/kmlparser.js @@ -168,19 +168,19 @@ ol.parser.KML = function(opt_options) { } } var symbolizers = undefined; - if (goog.isDef(container.styles)) { - symbolizers = container.styles[0].symbolizers; + if (goog.isDef(container['styles'])) { + symbolizers = container['styles'][0]['symbolizers']; - } else if (goog.isDef(container.styleMaps)) { - var styleMap = container.styleMaps[0]; - for (var i = 0, ii = styleMap.pairs.length; i < ii; i++) { - var pair = styleMap.pairs[i]; + } else if (goog.isDef(container['styleMaps'])) { + var styleMap = container['styleMaps'][0]; + for (var i = 0, ii = styleMap['pairs'].length; i < ii; i++) { + var pair = styleMap['pairs'][i]; if (pair.key === 'normal') { - if (goog.isDef(pair.styleUrl)) { - this.parseStyleUrl(obj, pair.styleUrl); - feature.set('styleUrl', pair.styleUrl); - } else if (goog.isDef(pair.styles)) { - symbolizers = pair.styles[0].symbolizers; + if (goog.isDef(pair['styleUrl'])) { + this.parseStyleUrl(obj, pair['styleUrl']); + feature.set('styleUrl', pair['styleUrl']); + } else if (goog.isDef(pair['styles'])) { + symbolizers = pair['styles'][0]['symbolizers']; } } } @@ -1101,14 +1101,14 @@ ol.parser.KML.prototype.applyStyle_ = function(feature, styles, styleMaps, for (i = 0, ii = styleMaps.length; i < ii; ++i) { var styleMap = styleMaps[i]; if (styleMap['id'] === styleUrl) { - for (var j = 0, jj = styleMap.pairs.length; j < jj; j++) { - var pair = styleMap.pairs[j]; + for (var j = 0, jj = styleMap['pairs'].length; j < jj; j++) { + var pair = styleMap['pairs'][j]; if (pair.key === 'normal') { - if (goog.isDef(pair.styleUrl)) { - styleUrl = pair.styleUrl; + if (goog.isDef(pair['styleUrl'])) { + styleUrl = pair['styleUrl']; styleUrl = styleUrl.substring(styleUrl.indexOf('#') + 1); - } else if (goog.isDef(pair.styles)) { - symbolizers = pair.styles[0]['symbolizers']; + } else if (goog.isDef(pair['styles'])) { + symbolizers = pair['styles'][0]['symbolizers']; } } } From a35219545e9f7560c1dc19428693cde43c880a16 Mon Sep 17 00:00:00 2001 From: Olivier Terral Date: Thu, 26 Sep 2013 17:26:43 +0200 Subject: [PATCH 7/7] Add new line at the end of file --- test/spec/ol/parser/kml/stylemap.kml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/ol/parser/kml/stylemap.kml b/test/spec/ol/parser/kml/stylemap.kml index 622becbfaa..70906c3025 100644 --- a/test/spec/ol/parser/kml/stylemap.kml +++ b/test/spec/ol/parser/kml/stylemap.kml @@ -26,4 +26,4 @@ - \ No newline at end of file +