UNPKG

data-fields

Version:

Render fields for various types of input.

1,634 lines (1,388 loc) 435 kB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var createField = require('../geojson') function inputField (state) { var field = createField(h, { editable: true, zoom: 12, value: state.geojson, center: [47.621958, -122.33636] }) return field } function displayField (state) { var field = createField(h, { zoom: 12, editable: false, center: [47.621958, -122.33636] }) // field.on('update', function (e, geojson) { // console.log('update?', e, geojson) // state.geojson = geojson // tree.update(state) // }) return field } function render (state) { return h('div.fields', [ h('div.editable', [inputField(state)]), h('div.static', [displayField(state)]) ]) } var initialState = { geojson: { type: 'FeatureCollection', features: [] } } var tree = vraf(initialState, render, require('virtual-dom')) document.body.querySelector('#geojson-basic').appendChild(tree.render()) },{"../geojson":10,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],2:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var form = require('data-form') var initialState = { properties: { location: { key: 'location', name: 'location', type: ['geoJSON'] } }, row: { value: { location: { type: 'Feature', geometry: { type: 'Point', coordinates: [-122.33636, 47.621958] } } } } } function onupdate (e, state) { tree.update(state) } function render (state) { state.onupdate = onupdate return form(h, state) } var tree = vraf(initialState, render, require('virtual-dom')) document.body.querySelector('#geojson-form').appendChild(tree.render()) },{"data-form":29,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],3:[function(require,module,exports){ var h = require('virtual-dom/h') var vraf = require('virtual-raf') var createMap = require('../utils/map') function render (state) { console.log(state.geojson) return h('div.widget', createMap(state.geojson, { editable: false, zoom: 12, setView: true, center: [47.621958, -122.33636], accessToken: 'pk.eyJ1Ijoic2V0aHZpbmNlbnQiLCJhIjoiSXZZXzZnUSJ9.Nr_zKa-4Ztcmc1Ypl0k5nw', onclick: newPoint })) function newPoint (e) { console.log(e) state.geojson.features.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [e.latlng.lng, e.latlng.lat] } }) tree.update(state) } } var initialState = { geojson: { type: 'FeatureCollection', features: [] } } var tree = vraf(initialState, render, require('virtual-dom')) document.body.querySelector('#geojson-widget').appendChild(tree.render()) },{"../utils/map":94,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],4:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var createField = require('../image') function editableField (state) { var field = createField(h, { value: state.imageURL, oninput: oninput }) function oninput (e) { tree.update({ imageURL: e.target.value }) } return field } function staticField (state) { return createField(h, { value: state.imageURL, editable: false }) } function render (state) { return h('div.fields', [ h('div.editable', [editableField(state)]), h('div.static', [staticField(state)]) ]) } var tree = vraf({ imageURL: 'http://placehold.it/50x50' }, render, require('virtual-dom')) document.body.querySelector('#image').appendChild(tree.render()) },{"../image":11,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],5:[function(require,module,exports){ require('./list') require('./string') require('./url') require('./image') require('./number') require('./geojson-basic') require('./geojson-form') require('./geojson-widget') },{"./geojson-basic":1,"./geojson-form":2,"./geojson-widget":3,"./image":4,"./list":6,"./number":7,"./string":8,"./url":9}],6:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var createField = require('../list') function inputField (state) { var field = createField(h, state) return field } function staticField (state) { var field = createField(h, { items: state.items, keys: state.keys, editable: false }) return field } function render (state) { return h('div.fields', [ h('div.editable', [inputField(state)]), h('div.static', [staticField(state)]) ]) } var state = { items: ['hi', 'ok', 'awesome'], keys: true } state.removeItem = function removeItem (e, items) { state.items = items tree.update(state) } state.onsubmit = function onsubmit (e, items, item) { state.items = items tree.update(state) } var tree = vraf(state, render, require('virtual-dom')) document.body.querySelector('#list').appendChild(tree.render()) },{"../list":12,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],7:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var numberField = require('../number') function editableField (state) { var field = numberField(h, { value: state.value, oninput: oninput }) function oninput (e) { tree.update({ value: e.target.value }) } return field } function staticField (state) { var field = numberField(h, { value: state.value, editable: false }) return field } function render (state) { return h('div.fields', [ h('div.editable', [editableField(state)]), h('div.static', [staticField(state)]) ]) } var tree = vraf({ value: 1000 }, render, require('virtual-dom')) document.body.querySelector('#number').appendChild(tree.render()) },{"../number":90,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],8:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var stringField = require('../string') function editableField (state) { var field = stringField(h, { value: state.message, oninput: oninput }) function oninput (e) { tree.update({ message: e.target.value }) } return field } function staticField (state) { var field = stringField(h, { value: state.message, editable: false }) return field } function render (state) { return h('div.fields', [ h('div.editable', [editableField(state)]), h('div.static', [staticField(state)]) ]) } var tree = vraf({ message: 'hi' }, render, require('virtual-dom')) document.body.querySelector('#string').appendChild(tree.render()) },{"../string":91,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],9:[function(require,module,exports){ var vraf = require('virtual-raf') var h = require('virtual-dom/h') var createField = require('../url') function editableField (state) { var field = createField(h, { value: state.url, oninput: oninput }) function oninput (e) { tree.update({ url: e.target.value }) } return field } function staticField (state) { return createField(h, { editable: false }, state.url) } function render (state) { return h('div.fields', [ h('div.editable', [editableField(state)]), h('div.static', [staticField(state)]) ]) } var tree = vraf({ url: 'example.com' }, render, require('virtual-dom')) document.body.querySelector('#url').appendChild(tree.render()) },{"../url":92,"virtual-dom":62,"virtual-dom/h":61,"virtual-raf":87}],10:[function(require,module,exports){ var extend = require('xtend') var createMap = require('./utils/map') var createClassName = require('./utils/classname') var defaultProps = { tagName: 'div', editable: true, size: 'normal', attributes: {} } /** Create a virtual-dom geojson data-field for use with [data-ui](https://github.com/editdata/data-ui). * @name createGeoJSONField * @param {Object} options an options object, including any properties you can pass to leaflet & virtual-dom/h * @param {String} options.accessToken mapbox access token for using their API * @param {Object} options.tileLayer Leaflet tilelayer, default is osm tiles * @param {String} options.imagePath path to leaflet images * @param {Boolean} options.editable false for static mode, default is true for editable mode * @returns field * @example * var createGeoJSONField = require('data-field-geojson') * var field = createGeoJSONField(h, options, geojsonObject) */ module.exports = function createGeoJSONField (h, options, geojsonObject) { options = extend(defaultProps, options) options.dataType = 'geojson' var value = geojsonObject || options.value var map = createMap(value, options) options.className = createClassName(options) return h(options.tagName, options, map) } },{"./utils/classname":93,"./utils/map":94,"xtend":89}],11:[function(require,module,exports){ var addhttp = require('addhttp') var extend = require('xtend') var createClassName = require('./utils/classname') var defaultProps = { tagName: 'input', editable: true, size: 'normal', attributes: {} } /** * Render a virtual-dom image data-field. * @param {function} h virtual-dom `h` function * @param {Object} options options object for `h` * @param {Boolean} options.display false for static mode, default is true for editable mode * @param {String} options.value any image url * @returns virtual-dom tree * @name createImageField * @example * var createImageField = require('data-field-image') * var field = createImageField(h, { value: 'http://example.com/example.jpg' }) */ module.exports = function createImageField (h, options, value) { options = extend(defaultProps, options) options.dataType = 'image' options.src = addhttp(value || options.src || options.value) options.className = createClassName(options) delete options.size if (!options.editable) options.tagName = 'img' return h(options.tagName, options, options.src) } },{"./utils/classname":93,"addhttp":13,"xtend":89}],12:[function(require,module,exports){ var extend = require('xtend') var convert = require('object-array-converter') var createClassName = require('data-field-classname') var listEditor = require('list-editor') var isarray = require('isarray') var defaultProps = { tagName: 'div', editable: true, size: 'normal', fieldType: 'input', attributes: {} } /** * Create a virtual-dom list (object or array) data-field for use with [data-ui](https://github.com/editdata/data-ui). * @param {function} h virtual-dom `h` function * @param {Object} properties an options object, including any properties you can pass to virtual-dom/h * @param {Boolean} properties.display true for display mode, default is false for input mode * @param {Boolean} properties.keys, false for array mode, default is true for object mode * @param {Object} properties.value an array or flat object * @param {Array} properties.value an array or flat object * @param {Object} value an array or flat object * @param {Array} value an array or flat object * @returns virtual-dom tree * @name createListField * @example * var createListField = require('data-field-string') * var field = createListField() * var tree = field.render(h, properties, ['a', 'b', 'c']) */ module.exports = function createListField (h, options, value) { options = extend(defaultProps, options) var keys = options.keys value = value || options.value options.items = value || options.items options.dataType = 'list' if (isarray(value)) value = convert.toObject(value) var items = [] if (!options.editable) { options.tagName = 'ul' items = Object.keys(options.items).map(function (key) { var item = options.items[key] var el = [] if (keys) el.push(h('span.data-field-list-key', key + ': ')) el.push(h('span.data-field-list-value', item)) return h('li.data-field-list-item', el) }) } else { items = [listEditor(h, options)] } options.className = createClassName(options) return h(options.tagName, options, items) } },{"data-field-classname":18,"isarray":45,"list-editor":50,"object-array-converter":52,"xtend":89}],13:[function(require,module,exports){ module.exports = function addhttp (url) { if (!/^https?\:\/\//.test(url)) { url = 'http://' + url } return url } },{}],14:[function(require,module,exports){ // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! // // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the 'Software'), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // when used in node, this will actually load the util module we depend on // versus loading the builtin util module as happens otherwise // this is a bug in node module loading as far as I am concerned var util = require('util/'); var pSlice = Array.prototype.slice; var hasOwn = Object.prototype.hasOwnProperty; // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) assert.AssertionError = function AssertionError(options) { this.name = 'AssertionError'; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; if (options.message) { this.message = options.message; this.generatedMessage = false; } else { this.message = getMessage(this); this.generatedMessage = true; } var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) { Error.captureStackTrace(this, stackStartFunction); } else { // non v8 browsers so we can have a stacktrace var err = new Error(); if (err.stack) { var out = err.stack; // try to strip useless frames var fn_name = stackStartFunction.name; var idx = out.indexOf('\n' + fn_name); if (idx >= 0) { // once we have located the function frame // we need to strip out everything before it (and its line) var next_line = out.indexOf('\n', idx + 1); out = out.substring(next_line + 1); } this.stack = out; } } }; // assert.AssertionError instanceof Error util.inherits(assert.AssertionError, Error); function replacer(key, value) { if (util.isUndefined(value)) { return '' + value; } if (util.isNumber(value) && !isFinite(value)) { return value.toString(); } if (util.isFunction(value) || util.isRegExp(value)) { return value.toString(); } return value; } function truncate(s, n) { if (util.isString(s)) { return s.length < n ? s : s.slice(0, n); } else { return s; } } function getMessage(self) { return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + self.operator + ' ' + truncate(JSON.stringify(self.expected, replacer), 128); } // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new assert.AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected)) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; function _deepEqual(actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (util.isBuffer(actual) && util.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { if (actual[i] !== expected[i]) return false; } return true; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (util.isDate(actual) && util.isDate(expected)) { return actual.getTime() === expected.getTime(); // 7.3 If the expected value is a RegExp object, the actual value is // equivalent if it is also a RegExp object with the same source and // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). } else if (util.isRegExp(actual) && util.isRegExp(expected)) { return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; // 7.4. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if (!util.isObject(actual) && !util.isObject(expected)) { return actual == expected; // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else { return objEquiv(actual, expected); } } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b) { if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) return false; // an identical 'prototype' property. if (a.prototype !== b.prototype) return false; // if one is a primitive, the other must be same if (util.isPrimitive(a) || util.isPrimitive(b)) { return a === b; } var aIsArgs = isArguments(a), bIsArgs = isArguments(b); if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) return false; if (aIsArgs) { a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b); } var ka = objectKeys(a), kb = objectKeys(b), key, i; // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] != kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key])) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected)) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } else if (actual instanceof expected) { return true; } else if (expected.call({}, actual) === true) { return true; } return false; } function _throws(shouldThrow, block, expected, message) { var actual; if (util.isString(expected)) { message = expected; expected = null; } try { block(); } catch (e) { actual = e; } message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } if (!shouldThrow && expectedException(actual, expected)) { fail(actual, expected, 'Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [true].concat(pSlice.call(arguments))); }; // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = function(block, /*optional*/message) { _throws.apply(this, [false].concat(pSlice.call(arguments))); }; assert.ifError = function(err) { if (err) {throw err;}}; var objectKeys = Object.keys || function (obj) { var keys = []; for (var key in obj) { if (hasOwn.call(obj, key)) keys.push(key); } return keys; }; },{"util/":58}],15:[function(require,module,exports){ },{}],16:[function(require,module,exports){ /*! * Cross-Browser Split 1.1.1 * Copyright 2007-2012 Steven Levithan <stevenlevithan.com> * Available under the MIT License * ECMAScript compliant, uniform cross-browser split method */ /** * Splits a string into an array of strings using a regex or string separator. Matches of the * separator are not included in the result array. However, if `separator` is a regex that contains * capturing groups, backreferences are spliced into the result each time `separator` is matched. * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably * cross-browser. * @param {String} str String to split. * @param {RegExp|String} separator Regex or string to use for separating the string. * @param {Number} [limit] Maximum number of items to include in the result array. * @returns {Array} Array of substrings. * @example * * // Basic use * split('a b c d', ' '); * // -> ['a', 'b', 'c', 'd'] * * // With limit * split('a b c d', ' ', 2); * // -> ['a', 'b'] * * // Backreferences in result array * split('..word1 word2..', /([a-z]+)(\d+)/i); * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] */ module.exports = (function split(undef) { var nativeSplit = String.prototype.split, compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group self; self = function(str, separator, limit) { // If `separator` is not a regex, use `nativeSplit` if (Object.prototype.toString.call(separator) !== "[object RegExp]") { return nativeSplit.call(str, separator, limit); } var output = [], flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6 (separator.sticky ? "y" : ""), // Firefox 3+ lastLastIndex = 0, // Make `global` and avoid `lastIndex` issues by working with a copy separator = new RegExp(separator.source, flags + "g"), separator2, match, lastIndex, lastLength; str += ""; // Type-convert if (!compliantExecNpcg) { // Doesn't need flags gy, but they don't hurt separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); } /* Values for `limit`, per the spec: * If undefined: 4294967295 // Math.pow(2, 32) - 1 * If 0, Infinity, or NaN: 0 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; * If negative number: 4294967296 - Math.floor(Math.abs(limit)) * If other: Type-convert, then use the above rules */ limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 limit >>> 0; // ToUint32(limit) while (match = separator.exec(str)) { // `separator.lastIndex` is not reliable cross-browser lastIndex = match.index + match[0].length; if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // Fix browsers whose `exec` methods don't consistently return `undefined` for // nonparticipating capturing groups if (!compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function() { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undef) { match[i] = undef; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // Avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }; return self; })(); },{}],17:[function(require,module,exports){ /** * cuid.js * Collision-resistant UID generator for browsers and node. * Sequential for fast db lookups and recency sorting. * Safe for element IDs and server-side lookups. * * Extracted from CLCTR * * Copyright (c) Eric Elliott 2012 * MIT License */ /*global window, navigator, document, require, process, module */ (function (app) { 'use strict'; var namespace = 'cuid', c = 0, blockSize = 4, base = 36, discreteValues = Math.pow(base, blockSize), pad = function pad(num, size) { var s = "000000000" + num; return s.substr(s.length-size); }, randomBlock = function randomBlock() { return pad((Math.random() * discreteValues << 0) .toString(base), blockSize); }, safeCounter = function () { c = (c < discreteValues) ? c : 0; c++; // this is not subliminal return c - 1; }, api = function cuid() { // Starting with a lowercase letter makes // it HTML element ID friendly. var letter = 'c', // hard-coded allows for sequential access // timestamp // warning: this exposes the exact date and time // that the uid was created. timestamp = (new Date().getTime()).toString(base), // Prevent same-machine collisions. counter, // A few chars to generate distinct ids for different // clients (so different computers are far less // likely to generate the same id) fingerprint = api.fingerprint(), // Grab some more chars from Math.random() random = randomBlock() + randomBlock(); counter = pad(safeCounter().toString(base), blockSize); return (letter + timestamp + counter + fingerprint + random); }; api.slug = function slug() { var date = new Date().getTime().toString(36), counter, print = api.fingerprint().slice(0,1) + api.fingerprint().slice(-1), random = randomBlock().slice(-2); counter = safeCounter().toString(36).slice(-4); return date.slice(-2) + counter + print + random; }; api.globalCount = function globalCount() { // We want to cache the results of this var cache = (function calc() { var i, count = 0; for (i in window) { count++; } return count; }()); api.globalCount = function () { return cache; }; return cache; }; api.fingerprint = function browserPrint() { return pad((navigator.mimeTypes.length + navigator.userAgent.length).toString(36) + api.globalCount().toString(36), 4); }; // don't change anything from here down. if (app.register) { app.register(namespace, api); } else if (typeof module !== 'undefined') { module.exports = api; } else { app[namespace] = api; } }(this.applitude || this)); },{}],18:[function(require,module,exports){ var assert = require('assert') module.exports = function createClassName (options) { options = options || {} assert.ok(options.dataType, 'options.dataType property required') assert.ok(options.fieldType, 'options.fieldType property required') assert.ok(options.size, 'options.size property required') return 'data-field data-field-' + options.dataType + ' data-field-' + options.fieldType + ' data-field-' + options.fieldType + '-' + options.size } },{"assert":14}],19:[function(require,module,exports){ var extend = require('xtend') var createMap = require('./utils/map') var createClassName = require('./utils/classname') var defaultProps = { tagName: 'div', editable: true, size: 'normal', attributes: {} } /** Create a virtual-dom geojson data-field for use with [data-ui](https://github.com/editdata/data-ui). * @name createGeoJSONField * @param {Object} options an options object, including any properties you can pass to leaflet & virtual-dom/h * @param {String} options.accessToken mapbox access token for using their API * @param {Object} options.tileLayer Leaflet tilelayer, default is osm tiles * @param {String} options.imagePath path to leaflet images * @param {Boolean} options.editable false for static mode, default is true for editable mode * @returns field * @example * var createGeoJSONField = require('data-field-geojson') * var field = createGeoJSONField(h, options, geojsonObject) */ module.exports = function createGeoJSONField (h, options, geojsonObject) { options = extend(defaultProps, options) options.dataType = 'geojson' var value = geojsonObject || options.value var map = createMap(value, options) options.className = createClassName(options) return h(options.tagName, options, map) } },{"./utils/classname":26,"./utils/map":27,"xtend":89}],20:[function(require,module,exports){ arguments[4][11][0].apply(exports,arguments) },{"./utils/classname":26,"addhttp":13,"dup":11,"xtend":89}],21:[function(require,module,exports){ module.exports = { string: require('./string'), number: require('./number'), url: require('./url'), geoJSON: require('./geoJSON'), image: require('./image'), list: require('./list') } },{"./geoJSON":19,"./image":20,"./list":22,"./number":23,"./string":24,"./url":25}],22:[function(require,module,exports){ var extend = require('xtend') var convert = require('object-array-converter') var createClassName = require('data-field-classname') var listEditor = require('list-editor') var isarray = require('isarray') var defaultProps = { tagName: 'div', editable: true, size: 'normal', fieldType: 'input', attributes: {} } /** * Create a virtual-dom list (object or array) data-field for use with [data-ui](https://github.com/editdata/data-ui). * @param {function} h virtual-dom `h` function * @param {Object} properties an options object, including any properties you can pass to virtual-dom/h * @param {Boolean} properties.display true for display mode, default is false for input mode * @param {Boolean} properties.keys, false for array mode, default is true for object mode * @param {Object} properties.value an array or flat object * @param {Array} properties.value an array or flat object * @param {Object} value an array or flat object * @param {Array} value an array or flat object * @returns virtual-dom tree * @name createListField * @example * var createListField = require('data-field-string') * var field = createListField() * var tree = field.render(h, properties, ['a', 'b', 'c']) */ module.exports = function createListField (h, options, value) { options = extend(defaultProps, options) var keys = options.keys value = value || options.value options.items = value options.dataType = 'list' if (isarray(value)) value = convert.toObject(value) var items = [] if (!options.editable) { options.tagName = 'ul' items = Object.keys(value).map(function (key) { var item = value[key] var el = [] if (keys) el.push(h('span.data-field-list-key', key + ': ')) el.push(h('span.data-field-list-value', item)) return h('li.data-field-list-item', el) }) } else { items = [listEditor({ items: value, keys: keys }, options)] } options.className = createClassName(options) return h(options.tagName, options, items) } },{"data-field-classname":18,"isarray":45,"list-editor":50,"object-array-converter":52,"xtend":89}],23:[function(require,module,exports){ var extend = require('xtend') var createClassName = require('./utils/classname') var defaultProps = { tagName: 'input', attributes: {}, editable: true, size: 'normal' } /** * Create a virtual-dom number data-field for use with [data-ui](https://github.com/editdata/data-ui). * @param {function} h virtual-dom `h` function * @param {Object} options Options object, including any properties you can pass to virtual-dom/h * @param {Boolean} options.editable false for static mode, default is true for editable mode * @param {String} options.value any number * @returns virtual-dom tree * @name createStringField * @example * var createStringField = require('data-field-string') * var field = createStringField(h, { value: 1000 }) */ module.exports = function NumberField (h, options, value) { options = extend(defaultProps, options) options.value = value || options.value options.type = options.dataType = 'number' options.fieldType = 'input' options.className = createClassName(options) delete options.size if (!options.editable) options.tagName = 'div' return h(options.tagName, options, options.value) } },{"./utils/classname":26,"xtend":89}],24:[function(require,module,exports){ var extend = require('xtend') var createClassName = require('./utils/classname') var defaultProps = { tagName: 'textarea', editable: true, size: 'normal', attributes: {} } /** * Create a virtual-dom string data-field for use with [data-ui](https://github.com/editdata/data-ui). * @param {Function} h virtual-dom `h` function * @param {Object} options Options object, including any properties you can pass to virtual-dom/h * @param {Boolean} options.editable false for a static field, default is true for an editable field * @param {String} options.value any string * @returns virtual-dom tree * @name createStringField * @example * var createStringField = require('data-field-string') * var field = createStringField(h, { value: 'example string' }) */ module.exports = function createStringField (h, options, value) { options = extend(defaultProps, options) options.value = value || options.value options.dataType = 'string' if (!options.editable) options.tagName = 'div' if (options.size === 'small') options.attributes.rows = 1 options.className = createClassName(options) return h(options.tagName, options, String(options.value)) } },{"./utils/classname":26,"xtend":89}],25:[function(require,module,exports){ var createClassName = require('./utils/classname') var extend = require('xtend') var addhttp = require('addhttp') var defaultProps = { tagName: 'input', editable: true, size: 'normal', attributes: {} } /** * Create a virtual-dom url data-field for use with [data-ui](https://github.com/editdata/data-ui). * @param {Object} options an options object, including any properties you can pass to virtual-dom/h * @param {Boolean} options.display true for display mode, default is false for input mode * @returns field * @name createURLField * @example * var createURLField = require('data-field-url') * var field = createURLField() * var vtree = field.render(h, {}, 'http://example.com') */ module.exports = function URLField (h, options, value) { options = extend(defaultProps, options) options.value = value || options.value options.dataType = 'url' options.href = addhttp(options.href || options.value) options.value = options.href options.className = createClassName(options) delete options.size if (!options.editable) options.tagName = 'a' return h(options.tagName, options, options.href) } },{"./utils/classname":26,"addhttp":13,"xtend":89}],26:[function(require,module,exports){ module.exports = function createClassName (options) { if (!options.hasOwnProperty('dataType')) throw Error('options.dataType property required') if (!options.hasOwnProperty('editable')) throw Error('options.editable property required') if (!options.hasOwnProperty('size')) throw Error('options.size property required') var className = 'data-field' className += ' data-field-' + options.dataType if (options.editable) { className += ' data-field-editable data-field-editable-' + options.size } if (options.className) className += ' ' + options.className return className } },{}],27:[function(require,module,exports){ var L = require('leaflet') require('leaflet-draw') module.exports = MapWidget L.Icon.Default.imagePath = 'assets/' function MapWidget (state, options) { if (!(this instanceof MapWidget)) return new MapWidget(state, options) var defaultState = { type: 'FeatureCollection', features: [] } if (!state || typeof state !== 'object') { this.data = defaultState } else if (state.type === 'Feature') { defaultState.features.push(state) this.data = defaultState } else if (state.type === 'FeatureCollection') { this.data = state } this.type = 'Widget' this.map = null this.features = null this.accessToken = options.accessToken this.display = options.display || false this.tiles = options.tileLayer || L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }) this.onclick = options.onclick this.onedit = options.onedit this.ondraw = options.ondraw this.onupdate = options.onupdate delete options.tiles delete options.display delete options.onclick this.options = options } MapWidget.prototype.refresh = function () { this.map.invalidateSize() } MapWidget.prototype.init = function () { var self = this var el = document.createElement('div') el.className = 'data-field-geojson-map-container' this.map = L.map(el, this.options) this.tiles.addTo(this.map) this.features = L.geoJson(this.data) this.map.addLayer(this.features) if (this.display) { this.features.on('click', function (e) { if (self.onclick) self.onclick(e) }) } else { var drawControl = new L.Control.Draw({ edit: { featureGroup: this.features } }) this.map.addControl(drawControl) this.map.on('draw:created', function (e) { self.features.addData(e.layer.toGeoJSON()) if (self.options.ondraw) self.options.ondraw(e, self.features.toGeoJSON()) if (self.options.onupdate) self.options.onupdate(e, self.features.toGeoJSON()) }) this.map.on('draw:edited', function (e) { if (self.options.onedit) self.options.onedit(e, self.features.toGeoJSON()) if (self.options.onupdate) self.options.onupdate(e, self.features.toGeoJSON()) }) } window.addEventListener('load', function (e) { self.map.invalidateSize() }) return el } MapWidget.prototype.update = function (previous, el) { this.map = this.map || previous.map this.features = this.features || previous.features this.features.clearLayers() this.features.addData(this.data) } MapWidget.prototype.destroy = function (el) {} },{"leaflet":48,"leaflet-draw":47}],28:[function(require,module,exports){ module.exports = function createFormHeader (h, options) { return h('div.data-form-header', [ h('div.data-form-actions', [ h('button.data-form-action.data-form-action-close.button', { onclick: options.onclick }, options.closeButton || 'close') ]) ]) } },{}],29:[function(require,module,exports){ /*global requestAnimationFrame*/ var formatter = require('data-format')() var fieldTypes = require('data-fields') var vhook = require('virtual-hook') var createHeader = require('./header') module.exports = Form function Form (h, options) { var activeColumnKey = options.activeColumnKey var oninput = options.oninput var onclick = options.onclick var ondestroy = options.ondestroy var onclose = options.onclose var onupdate = options.onupdate var properties = options.properties var row = options.row var columns = row.value var fields = [] var header if (typeof options.header === 'object') { header = options.header } else if (options.header !== false) { header = createHeader(h, { onclick: onClose }) } function onInput (rowKey, propertyKey) { return function (event) { var inputValue = event.target.value if (oninput) return oninput(event, rowKey, propertyKey, inputValue) } } function onClick (rowKey, propertyKey) { return function (event) { if (onclick) return onclick(event, rowKey, propertyKey) } } function onDestroy (event) { if (ondestroy) return ondestroy(event, row.key) } function onClose (event) { if (onclose) return onclose(event) } function onUpdate (event) { if (onupdate) return onupdate(event) } Object.keys(columns).forEach(function (propertyKey) { var property = formatter.findProperty(properties, propertyKey) var value = columns[propertyKey] var rowKey = row.key var type = property.type[0] var hooks = { hook: function (node, prop, prev) { if (propertyKey === activeColumnKey) { requestAnimationFrame(function () { node.focus() }) } } } var fieldOptions = { h: h, custom: vhook(hooks), id: 'item-property-' + row.key + '-' + propertyKey, attributes: { 'data-key': propertyKey }, value: columns[propertyKey], className: 'item-property-value', oninput: onInput(rowKey, propertyKey), onclick: onClick(rowKey, propertyKey), onupdate: onUpdate, center: [47.621958, -122.33636], zoom: 12 } if (type === 'array') { type = 'list' } if (type === 'object') { if (value.type && value.type === 'Feature') { type = 'geoJSON' } else { type = 'list' } } var field = fieldTypes[type](h, fieldOptions) var fieldwrapper = h('div.item-property-wrapper', [ h('span.item-property-label', property.name), field ]) fields.push(fieldwrapper) }) return h('div#item.active', [ h('div.item', [ header, h('button#destroyRow.small.button-orange', { onclick: onDestroy }, 'destroy row'), h('div.item-properties-wrapper', { attributes: { 'data-key': row.key } }, fields) ]) ]) } },{"./header":28,"data-fields":21,"data-format":30,"virtual-hook":86}],30:[function(require,module,exports){ var validator = require('is-my-json-valid') var extend = require('extend') var type = require('type-of') var isgeojson = require('is-geojson') var cuid = require('cuid') module.exports = function dataType (options) { options = options || {} var keyFormat = options.keyFormat || 'property-' function findProperty (props, id) { var name = id.name ? id.name : id var propkey = id.key ? id.key : id for (var key in props) { var nameMatch = props[key].name === name var keyMatch = props[key].key === propkey if (nameMatch || keyMatch) return props[key] } } function createProperty (key, value) { return { key: keyFormat + cuid(), name: key, type: initType(value), default: null } } function updateProperty (props, id, options) { var prop = findProperty(props, id) prop = extend(prop, options) props[prop.key] = prop return prop } function removeProperty (props, id) { var prop = findProperty(id) delete props[prop.key] } function validateProperty (props, prop, value) { if (typeof prop === 'string') { prop = findProperty(props, prop) if (!prop) return new Error('Property not found') } if (!prop) return new Error('Property, property key, or property name required as second argument') var validate = validator(props[prop.key]) return validate(value) } function convertToKeys (props, row) { var data = {} var prop Object.keys(row).forEach(function (key) { prop = findProperty(props, key) if (!prop) { prop = createProperty(key, row[key]) } if (!props[prop.key]) { props[prop.key] = prop } data[prop.key] = row[key] }) return data } function convertToNames (props, row) { var data = {} var prop Object.keys(row).forEach(function (key) { prop = findProperty(props, key) if (!prop) { prop = createProperty(key, row[key]) } data[prop.name] = row[key] }) return data } function convert (props, row, options) { options = options || {} if (options.to === 'names') { return convertToNames(props, row) } else { return convertToKeys(props, row) } } function initType (value) { return [type(value), 'null'] } function getType (props, key) { return props[key].type[0] } function isType (prop, checkType) { prop.type.some(function (type) { return type === checkType }) } function toGeoJSON (data, properties, options) { if (data.data && data.properties) { options = properties properties = data.properties data = data.data } options = options || {} var features = [] data.forEach(function (item, i) { features[i] = {} features[i].type = 'Feature' features[i].id = item.key features[i].geometry = item.geometry if (!options.convertToNames) { features[i].properties = item.value } else { features[i].properties = convertToNames(properties, item.value) } }) return features } function format (data, options) { options = options || {} options.key = options.key || 'key' options.value = options.value || 'value' var results = { properties: {}, data: [] } if (type(data) === 'array') { data.forEach(function (item) { var formatted = { key: null, value: {}, geometry: { type: 'Point', 'coordinates': [] } } if (isgeojson(item) && item.id && item.properties && item.geometry) { formatted.key = item.id formatted.value = item.properties formatted.geometry = item.geometry } else if (type(item) === 'obj