diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000000..111b15e321 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,4 @@ +{ + "-W030": true, + "-W083": true +} diff --git a/.travis.yml b/.travis.yml index a97e5659e1..ab29d9bd3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ before_install: - "git fetch origin refs/tags/v3.2.2:refs/tags/v3.2.2" - "git checkout tags/v3.2.2" - "cd ../.." + - "npm install" before_script: - "./build.py plovr" diff --git a/build.py b/build.py index 7962522c69..c05f89b4f1 100755 --- a/build.py +++ b/build.py @@ -21,6 +21,7 @@ if sys.platform == 'win32': 'JAVA': 'java.exe', 'JAR': 'jar.exe', 'JSDOC': 'jsdoc.cmd', + 'JSHINT': './node_modules/.bin/jshint', 'PYTHON': 'python.exe', 'PHANTOMJS': 'phantomjs.cmd' } @@ -71,6 +72,7 @@ if sys.platform == 'win32': else: variables.GIT = 'git' variables.GJSLINT = 'gjslint' + variables.JSHINT = './node_modules/.bin/jshint' variables.JAVA = 'java' variables.JAR = 'jar' variables.JSDOC = 'jsdoc' @@ -81,7 +83,8 @@ variables.BRANCH = output( '%(GIT)s', 'rev-parse', '--abbrev-ref', 'HEAD').strip() EXECUTABLES = [variables.GIT, variables.GJSLINT, variables.JAVA, variables.JAR, - variables.JSDOC, variables.PYTHON, variables.PHANTOMJS] + variables.JSDOC, variables.JSHINT, variables.PYTHON, + variables.PHANTOMJS] EXPORTS = [path for path in ifind('src') @@ -164,7 +167,7 @@ def report_sizes(t): virtual('default', 'build') -virtual('integration-test', 'lint', 'build', 'build-all', +virtual('integration-test', 'lint', 'jshint', 'build', 'build-all', 'test', 'build/examples/all.combined.js', 'check-examples', 'apidoc') @@ -172,7 +175,7 @@ virtual('build', 'build/ol.css', 'build/ol.js', 'build/ol-simple.js', 'build/ol-whitespace.js') -virtual('check', 'lint', 'build/ol-all.js', 'test') +virtual('check', 'lint', 'jshint', 'build/ol-all.js', 'test') virtual('todo', 'fixme') @@ -409,6 +412,15 @@ def build_lint_libtess_js_timestamp(t): t.touch() +virtual('jshint', 'build/jshint-timestamp') + + +@target('build/jshint-timestamp', SRC, EXAMPLES_SRC, SPEC, precious=True) +def build_jshint_timestamp(t): + t.run(variables.JSHINT, '--verbose', t.newer(t.dependencies)) + t.touch() + + def _strip_comments(lines): # FIXME this is a horribe hack, we should use a proper JavaScript parser # here diff --git a/examples/igc.js b/examples/igc.js index ac86418471..8597677ff2 100644 --- a/examples/igc.js +++ b/examples/igc.js @@ -174,7 +174,7 @@ $('#time').on('input', function(event) { var geometry = /** @type {ol.geom.LineString} */ (feature.getGeometry()); var coordinate = geometry.getCoordinateAtM(m, true); var highlight = feature.get('highlight'); - if (highlight == undefined) { + if (highlight === undefined) { highlight = new ol.Feature(new ol.geom.Point(coordinate)); feature.set('highlight', highlight); featureOverlay.addFeature(highlight); diff --git a/examples/modify-test.js b/examples/modify-test.js index 96c5c5d5a4..34ef8bb3eb 100644 --- a/examples/modify-test.js +++ b/examples/modify-test.js @@ -13,6 +13,7 @@ goog.require('ol.style.Style'); var styleFunction = (function() { + /* jshint -W069 */ var styles = {}; var image = new ol.style.Circle({ radius: 5, @@ -57,6 +58,7 @@ var styleFunction = (function() { return function(feature, resolution) { return styles[feature.getGeometry().getType()] || styles['default']; }; + /* jshint +W069 */ })(); var source = new ol.source.GeoJSON( @@ -165,6 +167,7 @@ var layer = new ol.layer.Vector({ }); var overlayStyle = (function() { + /* jshint -W069 */ var styles = {}; styles['Polygon'] = [ new ol.style.Style({ @@ -225,6 +228,7 @@ var overlayStyle = (function() { return function(feature, resolution) { return styles[feature.getGeometry().getType()]; }; + /* jshint +W069 */ })(); var select = new ol.interaction.Select({ diff --git a/examples/vector-labels.html b/examples/vector-labels.html index 8312c87256..db16e2f62c 100644 --- a/examples/vector-labels.html +++ b/examples/vector-labels.html @@ -68,7 +68,7 @@
- +

Points

@@ -157,7 +157,7 @@
- +

Lines

@@ -246,7 +246,7 @@
- +

Polygons

diff --git a/examples/vector-labels.js b/examples/vector-labels.js index 44cb2cfaa2..d4dc281292 100644 --- a/examples/vector-labels.js +++ b/examples/vector-labels.js @@ -13,56 +13,56 @@ goog.require('ol.style.Text'); var myDom = { - 'points': { - 'text': document.getElementById('points-text'), - 'align': document.getElementById('points-align'), - 'baseline': document.getElementById('points-baseline'), - 'rotation': document.getElementById('points-rotation'), - 'font': document.getElementById('points-font'), - 'weight': document.getElementById('points-weight'), - 'size': document.getElementById('points-size'), - 'offset-x': document.getElementById('points-offset-x'), - 'offset-y': document.getElementById('points-offset-y'), - 'color': document.getElementById('points-color'), - 'outline': document.getElementById('points-outline'), - 'outline-width': document.getElementById('points-outline-width'), - 'maxreso': document.getElementById('points-maxreso') + points: { + text: document.getElementById('points-text'), + align: document.getElementById('points-align'), + baseline: document.getElementById('points-baseline'), + rotation: document.getElementById('points-rotation'), + font: document.getElementById('points-font'), + weight: document.getElementById('points-weight'), + size: document.getElementById('points-size'), + offsetX: document.getElementById('points-offset-x'), + offsetY: document.getElementById('points-offset-y'), + color: document.getElementById('points-color'), + outline: document.getElementById('points-outline'), + outlineWidth: document.getElementById('points-outline-width'), + maxreso: document.getElementById('points-maxreso') }, - 'lines': { - 'text': document.getElementById('lines-text'), - 'align': document.getElementById('lines-align'), - 'baseline': document.getElementById('lines-baseline'), - 'rotation': document.getElementById('lines-rotation'), - 'font': document.getElementById('lines-font'), - 'weight': document.getElementById('lines-weight'), - 'size': document.getElementById('lines-size'), - 'offset-x': document.getElementById('lines-offset-x'), - 'offset-y': document.getElementById('lines-offset-y'), - 'color': document.getElementById('lines-color'), - 'outline': document.getElementById('lines-outline'), - 'outline-width': document.getElementById('lines-outline-width'), - 'maxreso': document.getElementById('lines-maxreso') + lines: { + text: document.getElementById('lines-text'), + align: document.getElementById('lines-align'), + baseline: document.getElementById('lines-baseline'), + rotation: document.getElementById('lines-rotation'), + font: document.getElementById('lines-font'), + weight: document.getElementById('lines-weight'), + size: document.getElementById('lines-size'), + offsetX: document.getElementById('lines-offset-x'), + offsetY: document.getElementById('lines-offset-y'), + color: document.getElementById('lines-color'), + outline: document.getElementById('lines-outline'), + outlineWidth: document.getElementById('lines-outline-width'), + maxreso: document.getElementById('lines-maxreso') }, - 'polygons': { - 'text': document.getElementById('polygons-text'), - 'align': document.getElementById('polygons-align'), - 'baseline': document.getElementById('polygons-baseline'), - 'rotation': document.getElementById('polygons-rotation'), - 'font': document.getElementById('polygons-font'), - 'weight': document.getElementById('polygons-weight'), - 'size': document.getElementById('polygons-size'), - 'offset-x': document.getElementById('polygons-offset-x'), - 'offset-y': document.getElementById('polygons-offset-y'), - 'color': document.getElementById('polygons-color'), - 'outline': document.getElementById('polygons-outline'), - 'outline-width': document.getElementById('polygons-outline-width'), - 'maxreso': document.getElementById('polygons-maxreso') + polygons: { + text: document.getElementById('polygons-text'), + align: document.getElementById('polygons-align'), + baseline: document.getElementById('polygons-baseline'), + rotation: document.getElementById('polygons-rotation'), + font: document.getElementById('polygons-font'), + weight: document.getElementById('polygons-weight'), + size: document.getElementById('polygons-size'), + offsetX: document.getElementById('polygons-offset-x'), + offsetY: document.getElementById('polygons-offset-y'), + color: document.getElementById('polygons-color'), + outline: document.getElementById('polygons-outline'), + outlineWidth: document.getElementById('polygons-outline-width'), + maxreso: document.getElementById('polygons-maxreso') } }; var getText = function(feature, resolution, dom) { - var type = dom['text'].value; - var maxResolution = dom['maxreso'].value; + var type = dom.text.value; + var maxResolution = dom.maxreso.value; var text = feature.getProperties().name; if (resolution > maxResolution) { @@ -80,17 +80,17 @@ var getText = function(feature, resolution, dom) { var createTextStyle = function(feature, resolution, dom) { - var align = dom['align'].value; - var baseline = dom['baseline'].value; - var size = dom['size'].value; - var offsetX = parseInt(dom['offset-x'].value, 10); - var offsetY = parseInt(dom['offset-y'].value, 10); - var weight = dom['weight'].value; - var rotation = parseFloat(dom['rotation'].value); - var font = weight + ' ' + size + ' ' + dom['font'].value; - var fillColor = dom['color'].value; - var outlineColor = dom['outline'].value; - var outlineWidth = parseInt(dom['outline-width'].value, 10); + var align = dom.align.value; + var baseline = dom.baseline.value; + var size = dom.size.value; + var offsetX = parseInt(dom.offsetX.value, 10); + var offsetY = parseInt(dom.offsetY.value, 10); + var weight = dom.weight.value; + var rotation = parseFloat(dom.rotation.value); + var font = weight + ' ' + size + ' ' + dom.font.value; + var fillColor = dom.color.value; + var outlineColor = dom.outline.value; + var outlineWidth = parseInt(dom.outlineWidth.value, 10); return new ol.style.Text({ textAlign: align, @@ -195,17 +195,17 @@ var map = new ol.Map({ }) }); -var refreshPoints = function() { +$('#refresh-points').click(function() { vectorPoints.setStyle(createPointStyleFunction()); -}; +}); -var refreshLines = function() { +$('#refresh-lines').click(function() { vectorLines.setStyle(createLineStyleFunction()); -}; +}); -var refreshPolygons = function() { +$('#refresh-polygons').click(function() { vectorPolygons.setStyle(createPolygonStyleFunction()); -}; +}); /** diff --git a/externs/closure-compiler.js b/externs/closure-compiler.js index a48a5827b0..eadd9ab7cf 100644 --- a/externs/closure-compiler.js +++ b/externs/closure-compiler.js @@ -52,3 +52,22 @@ Document.prototype.msFullscreenEnabled; /** @type {Element} */ Document.prototype.msFullscreenElement; + + +/** @type {number} */ +Touch.prototype.force; + +/** @type {number} */ +Touch.prototype.radiusX; + +/** @type {number} */ +Touch.prototype.radiusY; + +/** @type {number} */ +Touch.prototype.webkitForce; + +/** @type {number} */ +Touch.prototype.webkitRadiusX; + +/** @type {number} */ +Touch.prototype.webkitRadiusY; diff --git a/package.json b/package.json index 49896fe338..fd4defd2bf 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "devDependencies": { "closure-util": "~0.8.2", "async": "~0.2.10", - "htmlparser2": "~3.4.0" + "htmlparser2": "~3.4.0", + "jshint": "~2.4.4" } } diff --git a/src/ol/coordinate.js b/src/ol/coordinate.js index e027da504d..81838416aa 100644 --- a/src/ol/coordinate.js +++ b/src/ol/coordinate.js @@ -66,7 +66,7 @@ ol.coordinate.closestOnSegment = function(coordinate, segment) { var y2 = end[1]; var dx = x2 - x1; var dy = y2 - y1; - var along = (dx == 0 && dy == 0) ? 0 : + var along = (dx === 0 && dy === 0) ? 0 : ((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0); var x, y; if (along <= 0) { diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index b98ad70adc..dfe7385ace 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -1632,9 +1632,10 @@ ol.format.GML.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, var multiCurve = goog.object.get(context, 'multiCurve'); var parentNode = objectStack[objectStack.length - 1].node; goog.asserts.assert(ol.xml.isNode(parentNode)); + var nodeName; if (!goog.isArray(value)) { goog.asserts.assertInstanceof(value, ol.geom.Geometry); - var nodeName = value.getType(); + nodeName = value.getType(); if (nodeName === 'MultiPolygon' && multiSurface === true) { nodeName = 'MultiSurface'; } else if (nodeName === 'Polygon' && surface === true) { diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index 8dbe7cdba8..adfe131fee 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -490,6 +490,7 @@ ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) { ol.xml.setAttributeNS(node, null, 'lat', coordinate[1]); ol.xml.setAttributeNS(node, null, 'lon', coordinate[0]); var geometryLayout = goog.object.get(context, 'geometryLayout'); + /* jshint -W086 */ switch (geometryLayout) { case ol.geom.GeometryLayout.XYZM: if (coordinate[3] !== 0) { @@ -505,6 +506,7 @@ ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) { goog.object.set(properties, 'time', coordinate[2]); } } + /* jshint +W086 */ var orderedKeys = ol.format.GPX.WPT_TYPE_SEQUENCE_[namespaceURI]; var values = ol.xml.makeSequence(properties, orderedKeys); ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ diff --git a/src/ol/map.js b/src/ol/map.js index fbe46a52cd..a2b90479a1 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -1265,7 +1265,7 @@ ol.Map.prototype.renderFrame_ = function(time) { Array.prototype.push.apply( this.postRenderFunctions_, frameState.postRenderFunctions); - var idle = this.preRenderFunctions_.length == 0 && + var idle = this.preRenderFunctions_.length === 0 && !frameState.animate && !frameState.viewHints[ol.ViewHint.ANIMATING] && !frameState.viewHints[ol.ViewHint.INTERACTING]; diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index f2b7bdcb99..b1bd271e83 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -323,7 +323,7 @@ ol.MapBrowserEventHandler.prototype.isMouseActionButton_ = if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) { return pointerEvent.button == 1; } else { - return pointerEvent.button == 0; + return pointerEvent.button === 0; } }; diff --git a/src/ol/pointer/touchsource.js b/src/ol/pointer/touchsource.js index f621ef7207..db7351855c 100644 --- a/src/ol/pointer/touchsource.js +++ b/src/ol/pointer/touchsource.js @@ -193,9 +193,9 @@ ol.pointer.TouchSource.prototype.touchToPointer_ = e.detail = this.clickCount_; e.button = 0; e.buttons = 1; - e.width = inTouch['webkitRadiusX'] || inTouch['radiusX'] || 0; - e.height = inTouch['webkitRadiusY'] || inTouch['radiusY'] || 0; - e.pressure = inTouch['webkitForce'] || inTouch['force'] || 0.5; + e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; + e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; + e.pressure = inTouch.webkitForce || inTouch.force || 0.5; e.isPrimary = this.isPrimaryTouch_(inTouch); e.pointerType = ol.pointer.TouchSource.POINTER_TYPE; diff --git a/src/ol/source/imagewmssource.js b/src/ol/source/imagewmssource.js index fbff7861d6..dec6944151 100644 --- a/src/ol/source/imagewmssource.js +++ b/src/ol/source/imagewmssource.js @@ -272,7 +272,9 @@ ol.source.ImageWMS.prototype.getRequestUrl_ = params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode(); if (!('STYLES' in this.params_)) { + /* jshint -W053 */ goog.object.set(params, 'STYLES', new String('')); + /* jshint +W053 */ } if (pixelRatio != 1) { diff --git a/src/ol/source/tilewmssource.js b/src/ol/source/tilewmssource.js index 9a3a927f93..98336f839a 100644 --- a/src/ol/source/tilewmssource.js +++ b/src/ol/source/tilewmssource.js @@ -237,7 +237,9 @@ ol.source.TileWMS.prototype.getRequestUrl_ = params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode(); if (!('STYLES' in this.params_)) { + /* jshint -W053 */ goog.object.set(params, 'STYLES', new String('')); + /* jshint +W053 */ } if (pixelRatio != 1) { diff --git a/src/ol/source/wmtssource.js b/src/ol/source/wmtssource.js index bd0d7c514b..9bd0ce9c5c 100644 --- a/src/ol/source/wmtssource.js +++ b/src/ol/source/wmtssource.js @@ -243,6 +243,8 @@ ol.source.WMTS.prototype.updateDimensions = function(dimensions) { */ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, layer) { + /* jshint -W069 */ + // TODO: add support for TileMatrixLimits var layers = wmtsCap['contents']['layers']; @@ -328,4 +330,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, layer) { style: style, dimensions: dimensions }; + + /* jshint +W069 */ + }; diff --git a/test/spec/ol/pointer/touchsource.test.js b/test/spec/ol/pointer/touchsource.test.js index c01c2e2608..a090007ab1 100644 --- a/test/spec/ol/pointer/touchsource.test.js +++ b/test/spec/ol/pointer/touchsource.test.js @@ -118,8 +118,7 @@ describe('ol.pointer.TouchSource', function() { }); function simulateTouchEvent(type, changedTouches, touches) { - var touches = goog.isDef(touches) ? - touches : changedTouches; + touches = goog.isDef(touches) ? touches : changedTouches; var event = new goog.events.BrowserEvent({ type: type, diff --git a/test/spec/ol/proj/proj.test.js b/test/spec/ol/proj/proj.test.js index b373299a58..7cbc59d016 100644 --- a/test/spec/ol/proj/proj.test.js +++ b/test/spec/ol/proj/proj.test.js @@ -285,7 +285,7 @@ describe('ol.proj', function() { units: units, extent: extent }); - var transform = function(input, output, dimension) {return input}; + var transform = function(input, output, dimension) {return input;}; ol.proj.addTransform(foo, bar, transform); expect(ol.proj.transforms_).not.to.be(undefined); expect(ol.proj.transforms_.foo).not.to.be(undefined);