<commit_before>// CAMIC is an instance of caMicroscope core
let $CAMIC = null;
// for all instances of UI components
const $UI = {};

const $D = {
    pages: {
        home: './table.html',
        table: './table.html'
    },
    params: null // parameter from url - slide Id and status in it (object).
};

// initialize viewer page
// setting core functionalities
function initialize() {
    // start initial
    const opt = {
        hasZoomControl: true,
        hasDrawLayer: false,
        hasLayerManager: true,
        hasScalebar: true,
        hasMeasurementTool: true
    };

    // set states if exist
    if ($D.params.states) {
        opt.states = $D.params.states;
    }

    try {
        $CAMIC = new CaMic("main_viewer", $D.params.slideId, opt);
    } catch (error) {
        Loading.close();
        $UI.message.addError('Core Initialization Failed');
        console.error(error);
        return;
    }

    $CAMIC.loadImg(function (e) {
        // image loaded
        if (e.hasError) {
            $UI.message.addError(e.message)
        }
    });

    // draw something
    $CAMIC.viewer.addOnceHandler('open', function (e) {
        // ready to draw

        // Display by fetching data
        // _1n7w6ahx2
        fetchJSON('/data/Mark/multi?name=["_1n7w6ahx2"]&slide=CMU1', queryPoly);

        // Display with 'data1' coordinates
        $CAMIC.viewer.omanager.addOverlay({id: 'id01', data: data1, render: renderPoly, isShow: true});

    });

}

/**
 * renders a polygon onto a layer or canvas
 * @param context - the canvas context or layer
 * @param points - a list of coordinates, each in form [x,y]
 **/
function renderPoly(context, points) {

    // console.log('length', points.length, 'points', points);

    context.lineWidth = 10;
    context.strokeStyle = 'yellow';
    context.fillStyle = 'rgba(125,125,125,.4)';
    context.moveTo(points[0][0], points[0][1]);
    context.lineTo(points[0][0], points[0][1]);
    context.beginPath();

    points.slice(1).forEach(function (coord) {
        let x = coord[0];
        let y = coord[1];
        context.lineTo(x, y);
    });

    context.lineTo(points[0][0], points[0][1]);
    context.closePath();
    context.stroke();
}

function queryPoly(item, item1) {

    //console.log('item1', JSON.stringify(item1));

    let array1 = item1[0].geometries.features[0].geometry.coordinates[0];
    //console.log('array1', array1);

    const map1 = array1.map(x => {
        const img_point = $CAMIC.viewer.viewport.viewportToImageCoordinates(x[0], x[1]);
        return [img_point.x, img_point.y];
    });
    //console.log('map1', map1);

    $CAMIC.viewer.omanager.addOverlay({id: 'id02', data: map1, render: renderPoly, isShow: true});
    $CAMIC.viewer.omanager.updateView();

}

function fetchJSON(url, options, callback) {

    if (typeof options === 'function') {
        callback = options;
        options = {}
    }

    options = options || {};

    const headers = (options.headers || (options.headers = {}));
    headers.Accept = 'application/json';

    fetch(url, options)
        .then(response => response.json())
        .then(json => callback(null, json), callback)
}

// image coordinates
const data1 = [
    [1000, 1000],
    [1100, 1000],
    [1200, 1100],
    [1100, 1200],
    [1000, 1200],
    [900, 1100],
    [1000, 1000],
];
<commit_msg>added query by bbox<commit_after>// CAMIC is an instance of caMicroscope core
let $CAMIC = null;
// for all instances of UI components
const $UI = {};

const $D = {
    pages: {
        home: './table.html',
        table: './table.html'
    },
    params: null // parameter from url - slide Id and status in it (object).
};

// initialize viewer page
// setting core functionalities
function initialize() {
    // start initial
    const opt = {
        hasZoomControl: true,
        hasDrawLayer: false,
        hasLayerManager: true,
        hasScalebar: true,
        hasMeasurementTool: true
    };

    // set states if exist
    if ($D.params.states) {
        opt.states = $D.params.states;
    }

    try {
        $CAMIC = new CaMic("main_viewer", $D.params.slideId, opt);
    } catch (error) {
        Loading.close();
        $UI.message.addError('Core Initialization Failed');
        console.error(error);
        return;
    }

    $CAMIC.loadImg(function (e) {
        // image loaded
        if (e.hasError) {
            $UI.message.addError(e.message)
        }
    });

    // draw something
    $CAMIC.viewer.addOnceHandler('open', function (e) {
        // ready to draw

        getLayerId();

        // Display by fetching data
        // _1n7w6ahx2
        let url='/data/Mark/multi?name=["_1n7w6ahx2"]&slide=CMU1';
        fetchJSON(url, queryPoly);

        // Display with 'data1' coordinates
        $CAMIC.viewer.omanager.addOverlay({id: 'id01', data: this.data1, render: renderPoly, isShow: true});

        // Display using spatial query
        // _rh5xco7oc
        url='http://nexi-bmi.uhmc.sunysb.edu:4010/data/Mark/findBound?x0=0.45&y0=0.62&x1=0.53&y1=0.68';
        fetchJSON(url, queryPoly);

    });

}

/**
 * renders a polygon onto a layer or canvas
 * @param context - the canvas context or layer
 * @param points - a list of coordinates, each in form [x,y]
 **/
function renderPoly(context, points) {

    // console.log('length', points.length, 'points', points);

    context.lineWidth = 10;
    context.strokeStyle = 'yellow';
    context.fillStyle = 'rgba(125,125,125,.4)';
    context.moveTo(points[0][0], points[0][1]);
    context.lineTo(points[0][0], points[0][1]);
    context.beginPath();

    points.slice(1).forEach(function (coord) {
        let x = coord[0];
        let y = coord[1];
        context.lineTo(x, y);
    });

    context.lineTo(points[0][0], points[0][1]);
    context.closePath();
    context.stroke();
}

function queryPoly(item, item1) {

    //console.log('item1', JSON.stringify(item1));

    let array1 = item1[0].geometries.features[0].geometry.coordinates[0];
    //console.log('array1', array1);

    const map1 = array1.map(x => {
        const img_point = $CAMIC.viewer.viewport.viewportToImageCoordinates(x[0], x[1]);
        return [img_point.x, img_point.y];
    });
    //console.log('map1', map1);

    $CAMIC.viewer.omanager.addOverlay({id: getLayerId(), data: map1, render: renderPoly, isShow: true});
    $CAMIC.viewer.omanager.updateView();

}

function fetchJSON(url, options, callback) {

    if (typeof options === 'function') {
        callback = options;
        options = {}
    }

    options = options || {};

    const headers = (options.headers || (options.headers = {}));
    headers.Accept = 'application/json';

    fetch(url, options)
        .then(response => response.json())
        .then(json => callback(null, json), callback)
}

// image coordinates
const data1 = [
    [1000, 1000],
    [1100, 1000],
    [1200, 1100],
    [1100, 1200],
    [1000, 1200],
    [900, 1100],
    [1000, 1000],
];

layerId = 'id1';

function getLayerId()
{
    let tmp = this.layerId;
    let pre = tmp.slice(0, -1);
    let num = tmp.substr(-1);
    let integer = parseInt(num);
    integer = integer + 1;
    this.layerId = (pre + integer);

    return this.layerId;
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const electronLocalshortcut = require('electron-localshortcut')
const messages = require('../js/constants/messages')

module.exports.register = (win) => {
  // Most of these events will simply be listened to by the app store and acted
  // upon.  However sometimes there are no state changes, for example with focusing
  // the URL bar.  In those cases it's acceptable for the individual components to
  // listen to the events.
  const simpleWebContentEvents = [
    ['CmdOrCtrl+Shift+]', messages.SHORTCUT_NEXT_TAB],
    ['CmdOrCtrl+Shift+[', messages.SHORTCUT_PREV_TAB],
    ['CmdOrCtrl+Right', messages.SHORTCUT_ACTIVE_FRAME_FORWARD],
    ['CmdOrCtrl+Left', messages.SHORTCUT_ACTIVE_FRAME_BACK],
    ['CmdOrCtrl+9', messages.SHORTCUT_SET_ACTIVE_FRAME_TO_LAST]
  ]

  // Tab ordering shortcuts
  Array.from(new Array(8), (x, i) => i).reduce((list, i) => {
    list.push(['CmdOrCtrl+' + String(i + 1), messages.SHORTCUT_SET_ACTIVE_FRAME_BY_INDEX, i])
    return list
  }, simpleWebContentEvents)

  simpleWebContentEvents.forEach((shortcutEventName) =>
    electronLocalshortcut.register(win, shortcutEventName[0], () => {
      BrowserWindow.getFocusedWindow().webContents.send(shortcutEventName[1], shortcutEventName[2])
    }))
}

module.exports.unregister = (win) => {
  electronLocalshortcut.unregisterAll(win)
}
<commit_msg>F5 and CTRL+F5 options on Windows<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const electronLocalshortcut = require('electron-localshortcut')
const messages = require('../js/constants/messages')

module.exports.register = (win) => {
  // Most of these events will simply be listened to by the app store and acted
  // upon.  However sometimes there are no state changes, for example with focusing
  // the URL bar.  In those cases it's acceptable for the individual components to
  // listen to the events.
  const simpleWebContentEvents = [
    ['CmdOrCtrl+Shift+]', messages.SHORTCUT_NEXT_TAB],
    ['CmdOrCtrl+Shift+[', messages.SHORTCUT_PREV_TAB],
    ['CmdOrCtrl+Right', messages.SHORTCUT_ACTIVE_FRAME_FORWARD],
    ['CmdOrCtrl+Left', messages.SHORTCUT_ACTIVE_FRAME_BACK],
    ['CmdOrCtrl+9', messages.SHORTCUT_SET_ACTIVE_FRAME_TO_LAST]
  ]

  if (process.platform === 'win32') {
    simpleWebContentEvents.push(
      ['F5', messages.SHORTCUT_ACTIVE_FRAME_RELOAD],
      ['Ctrl+F5', messages.SHORTCUT_ACTIVE_FRAME_CLEAN_RELOAD])
  }

  // Tab ordering shortcuts
  Array.from(new Array(8), (x, i) => i).reduce((list, i) => {
    list.push(['CmdOrCtrl+' + String(i + 1), messages.SHORTCUT_SET_ACTIVE_FRAME_BY_INDEX, i])
    return list
  }, simpleWebContentEvents)

  simpleWebContentEvents.forEach((shortcutEventName) =>
    electronLocalshortcut.register(win, shortcutEventName[0], () => {
      BrowserWindow.getFocusedWindow().webContents.send(shortcutEventName[1], shortcutEventName[2])
    }))
}

module.exports.unregister = (win) => {
  electronLocalshortcut.unregisterAll(win)
}
<|endoftext|>


<commit_before>var passport = require('passport');
var Account = require('./models/account');
var Pet = require('./models/pet');

module.exports = function (app) {

  app.get('/', function (req, res) {
      if (req.user) {
        res.redirect('/pets');
      } else {
        res.render('index', { user : req.user });
      }
  });

  app.get('/register', function(req, res) {
      res.render('register', { });
  });

  app.post('/register', function(req, res) {
    Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
        if (err) {
            return res.render('register', { info: "Sorry. That username already exists." });
        }

        passport.authenticate('local')(req, res, function () {
          res.redirect('/');
        });
    });
  });

  app.get('/login', function(req, res) {
      res.render('login', { user : req.user });
  });

  app.post('/login', passport.authenticate('local'), function(req, res) {
      res.redirect('/pets');
  });

  app.get('/logout', function(req, res) {
      req.logout();
      res.redirect('/');
  });

  app.get('/pets', function(req, res) {
    if (req.user) {
      Pet.find({ owner: req.user.username }, function (err, pets) {
        if (err) return console.error(err);
        if (!pets) {
          res.render('add-pet', { user : req.user });
        } else {
          res.render('pets', { user : req.user, pets : pets });
        }
      });
    } else {
      res.redirect('/login');
    }
  });

  app.post('/add-pet', function(req, res) {
    var url_name = req.body.name.toLowerCase();
    var pet = new Pet({
      name : req.body.name,
      owner : req.body.owner,
      url_name : url_name,
      birthday : Date.now(),
      fed_at : Date.now(),
      slept_at : Date.now(),
      played_at : Date.now()
  });
    pet.save(function(err, pet) {
      if (err) return console.error(err);
    });

    res.redirect('/pets');
  });

  app.get('/add-pet', function(req, res) {
    if (req.user) {
      res.render('add-pet', { user : req.user });
    } else {
      res.redirect('/login');
    }
  });

  app.get('/pet/*', function(req, res) {
    if (req.user) {
      var action = req.body.action;
      Pet.findOne({
        owner: req.user.username,
        url_name: req.params[0]
      }, function(err, pet) {
        if (err) return console.error(err);
        if (req.param('json')) {
          res.json({pet : pet});
        } else {
          res.render('pet', { user : req.user, pet : pet });
        }
      });
    }
  });

  app.post('/pet/*', function(req, res) {
    if (req.user) {
      if ( req.body.action ) {
        var key;
        switch(req.body.action) {
          case 'feed':
            key = 'fed_at';
            break;
          case 'sleep':
            key = 'slept_at';
            break;
          case 'play':
            key = 'played_at';
            break;
        }
        var conditions = {
          owner : req.user.username,
          url_name : req.params[0]
        },
        update = {
          [key] : Date.now()
        }
        Pet.update(conditions, update, function(){
          Pet.findOne({
            owner: req.user.username,
            url_name: req.params[0]
          }, function(err, pet) {
            if (err) return console.error(err);

            res.json({pet : pet});
            /*if (req.param('json')) {
            } else {
              res.render('pet', { user : req.user, pet : pet });
            }*/
          });
        });

      }
    }
  });

  app.get('/pet/:url_name(*)/play', function(req, res) {
    if (req.user) {
      Pet.findOne({
        owner: req.user.username,
        url_name: req.params.url_name
      }, function(err, pet) {
        if (err) return console.error(err);

        res.render('play', { user : req.user, pet : pet, url_name : url_name });
      });
    }
  });

  app.post('/remove/*', function(req, res) {
    if (req.user) {
      Pet.findOne({
        owner: req.user.username,
        url_name: req.params[0]
      }, function(err, pet) {
        if (err) return console.error(err);
        if ( req.body.delete === 'delete') {
          if ( req.body.confirm !== 'true' ) {
            res.render('pet', { user : req.user, pet : pet, msg : 'You must check the confirmation box to delete this pet' });
          }

        res.render('pet', { user : req.user, pet : pet });

        }
      });

    } else {
      res.redirect('/login');
    }
  });
};
<commit_msg>Delete route update<commit_after>var passport = require('passport');
var Account = require('./models/account');
var Pet = require('./models/pet');

module.exports = function (app) {

  app.get('/', function (req, res) {
      if (req.user) {
        res.redirect('/pets');
      } else {
        res.render('index', { user : req.user });
      }
  });

  app.get('/register', function(req, res) {
      res.render('register', { });
  });

  app.post('/register', function(req, res) {
    Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
        if (err) {
            return res.render('register', { info: "Sorry. That username already exists." });
        }

        passport.authenticate('local')(req, res, function () {
          res.redirect('/');
        });
    });
  });

  app.get('/login', function(req, res) {
      res.render('login', { user : req.user });
  });

  app.post('/login', passport.authenticate('local'), function(req, res) {
      res.redirect('/pets');
  });

  app.get('/logout', function(req, res) {
      req.logout();
      res.redirect('/');
  });

  app.get('/pets', function(req, res) {
    if (req.user) {
      Pet.find({ owner: req.user.username }, function (err, pets) {
        if (err) return console.error(err);
        if (!pets) {
          res.render('add-pet', { user : req.user });
        } else {
          res.render('pets', { user : req.user, pets : pets });
        }
      });
    } else {
      res.redirect('/login');
    }
  });

  app.post('/add-pet', function(req, res) {
    var url_name = req.body.name.toLowerCase();
    var pet = new Pet({
      name : req.body.name,
      owner : req.body.owner,
      url_name : url_name,
      birthday : Date.now(),
      fed_at : Date.now(),
      slept_at : Date.now(),
      played_at : Date.now()
  });
    pet.save(function(err, pet) {
      if (err) return console.error(err);
    });

    res.redirect('/pets');
  });

  app.get('/add-pet', function(req, res) {
    if (req.user) {
      res.render('add-pet', { user : req.user });
    } else {
      res.redirect('/login');
    }
  });

  app.get('/pet/*', function(req, res) {
    if (req.user) {
      var action = req.body.action;
      Pet.findOne({
        owner: req.user.username,
        url_name: req.params[0]
      }, function(err, pet) {
        if (err) return console.error(err);
        if (req.param('json')) {
          res.json({pet : pet});
        } else {
          res.render('pet', { user : req.user, pet : pet });
        }
      });
    }
  });

  app.post('/pet/*', function(req, res) {
    if (req.user) {
      if ( req.body.action ) {
        var key;
        switch(req.body.action) {
          case 'feed':
            key = 'fed_at';
            break;
          case 'sleep':
            key = 'slept_at';
            break;
          case 'play':
            key = 'played_at';
            break;
        }
        var conditions = {
          owner : req.user.username,
          url_name : req.params[0]
        },
        update = {
          [key] : Date.now()
        }
        Pet.update(conditions, update, function(){
          Pet.findOne({
            owner: req.user.username,
            url_name: req.params[0]
          }, function(err, pet) {
            if (err) return console.error(err);

            res.json({pet : pet});
            /*if (req.param('json')) {
            } else {
              res.render('pet', { user : req.user, pet : pet });
            }*/
          });
        });

      }
    }
  });

  app.get('/pet/:url_name(*)/play', function(req, res) {
    if (req.user) {
      Pet.findOne({
        owner: req.user.username,
        url_name: req.params.url_name
      }, function(err, pet) {
        if (err) return console.error(err);

        res.render('play', { user : req.user, pet : pet, url_name : url_name });
      });
    }
  });

  app.post('/remove/*', function(req, res) {
    if (req.user) {
      Pet.findOne({
        owner: req.user.username,
        url_name: req.params[0]
      }, function(err, pet) {
        if (err) return console.error(err);
        if ( req.body.delete === 'delete') {
          if ( req.body.confirm !== 'true' ) {
            res.render('pet', { user : req.user, pet : pet, msg : 'You must check the confirmation box to delete this pet' });
          } else {
            res.render('pet', { user : req.user, pet : pet, msg : 'Pet will be deleted' });

          }

        } else {
          res.render('pet', { user : req.user, pet : pet });
        }
      });

    } else {
      res.redirect('/login');
    }
  });
};
<|endoftext|>


<commit_before>import React                from 'react';
import { merge }            from 'timm';
import { bindAll }          from '../gral/helpers';
import {
  COLORS, KEYS,
  UNICODE,
  NULL_STRING,
  IS_IOS,
}                           from '../gral/constants';
import {
  flexContainer, flexItem,
  GLOW,
  inputReset, INPUT_DISABLED,
}                           from '../gral/styles';
import {
  createShortcut,
  registerShortcut,
  unregisterShortcut,
}                           from '../gral/keys';
import input                from '../hocs/input';
import {
  ListPicker,
  LIST_SEPARATOR_KEY,
}                           from '../inputs/listPicker';
import IosFloatWrapper      from '../inputs/iosFloatWrapper';
import {
  floatAdd,
  floatDelete,
  floatUpdate,
  warnFloats,
}                           from '../components/floats';
import Icon                 from '../components/icon';

const LIST_SEPARATOR = {
  value: LIST_SEPARATOR_KEY,
  label: LIST_SEPARATOR_KEY,
};

function toInternalValue(val) { return val != null ? JSON.stringify(val) : NULL_STRING; }
function toExternalValue(val) { return val !== NULL_STRING ? JSON.parse(val) : null; }
function isNull(val) { return val === NULL_STRING; }

// ==========================================
// Component
// ==========================================
class SelectCustomBase extends React.Component {
  static propTypes = {
    disabled:               React.PropTypes.bool,
    items:                  React.PropTypes.array.isRequired,
    required:               React.PropTypes.bool,
    inlinePicker:           React.PropTypes.bool,
    children:               React.PropTypes.any,
    onClickItem:            React.PropTypes.func,
    onCloseFloat:           React.PropTypes.func,
    floatPosition:          React.PropTypes.string,
    floatAlign:             React.PropTypes.string,
    floatZ:                 React.PropTypes.number,
    style:                  React.PropTypes.object,
    twoStageStyle:          React.PropTypes.bool,
    accentColor:            React.PropTypes.string,
    // Input HOC
    curValue:               React.PropTypes.string.isRequired,
    onChange:               React.PropTypes.func.isRequired,
    registerOuterRef:       React.PropTypes.func.isRequired,
    fFocused:               React.PropTypes.bool.isRequired,
    keyDown:                React.PropTypes.object,
  };
  static defaultProps = {
    accentColor:            COLORS.accent,
  };

  constructor(props) {
    super(props);
    this.state = { fFloat: false };
    this.keyDown = undefined;
    bindAll(this, [
      'registerTitleRef',
      'onMouseDownTitle',
      'onClickItem',
    ]);
  }

  componentWillMount() {
    this.prepareItems(this.props.items, this.props.required);
  }

  componentDidMount() {
    if (!this.props.inlinePicker) {
      warnFloats(this.constructor.name);
    }
    this.registerShortcuts();
  }

  componentWillReceiveProps(nextProps) {
    const { keyDown, items, required, fFocused } = nextProps;
    if (keyDown !== this.props.keyDown) this.processKeyDown(keyDown);
    if (items !== this.props.items || required !== this.props.required) {
      this.unregisterShortcuts();
      this.prepareItems(items, required);
    }
    if (fFocused !== this.props.fFocused) {
      this.setState({ fFloat: fFocused });
    }
  }

  componentDidUpdate() {
    this.renderFloat();
  }

  componentWillUnmount() {
    floatDelete(this.floatId);
    this.unregisterShortcuts();
  }

  // ==========================================
  // Render
  // ==========================================
  render() {
    let out;
    if (this.props.inlinePicker) {
      out = this.renderPicker();
    } else if (this.props.children) {
      out = this.renderProvidedTitle();
    } else {
      out = this.renderDefaultTitle();
    }
    return out;
  }

  renderProvidedTitle() {
    const elTitle = React.cloneElement(this.props.children, {
      ref: this.registerTitleRef,
    });
    return IS_IOS ?

        {elTitle}
        {this.renderFloatForIos()}
       :
      elTitle;
  }

  renderDefaultTitle() {
    const { curValue } = this.props;
    let label = UNICODE.nbsp;
    if (curValue !== NULL_STRING) {
      for (let i = 0; i < this.items.length; i++) {
        if (this.items[i].value === curValue) {
          label = this.items[i].label;
          break;
        }
      }
    }
    const caretIcon = this.state.fFloat ? 'caret-up' : 'caret-down';
    return (

        {label}

        <Icon icon={caretIcon} style={style.caret} />
        {IS_IOS && this.renderFloatForIos()}

    );
  }

  renderFloat() {
    if (this.props.inlinePicker) return;
    if (IS_IOS) return;
    const { fFloat } = this.state;

    // Remove float
    if (!fFloat && this.floatId != null) {
      floatDelete(this.floatId);
      this.floatId = null;
      this.props.onCloseFloat && this.props.onCloseFloat();
      return;
    }

    // Create or update float
    if (fFloat) {
      const { floatZ, floatPosition, floatAlign } = this.props;
      const floatOptions = {
        position: floatPosition,
        align: floatAlign,
        zIndex: floatZ,
        limitSize: true,
        getAnchorNode: () => this.refTitle,
        children: this.renderPicker(),
      };
      if (this.floatId == null) {
        this.floatId = floatAdd(floatOptions);
      } else {
        floatUpdate(this.floatId, floatOptions);
      }
    }
  }

  renderFloatForIos() {
    if (!this.state.fFloat) return null;
    const { floatPosition, floatAlign, floatZ } = this.props;
    return (
      <IosFloatWrapper
        floatPosition={floatPosition}
        floatAlign={floatAlign}
        floatZ={floatZ}
      >
        {this.renderPicker()}
      </IosFloatWrapper>
    );
  }

  renderPicker() {
    const {
      inlinePicker,
      registerOuterRef,
      curValue, onChange,
      disabled, fFocused,
      style: styleList,
      twoStageStyle, accentColor,
    } = this.props;
    return (
      <ListPicker
        registerOuterRef={inlinePicker ? registerOuterRef : undefined}
        items={this.items}
        curValue={curValue}
        onChange={onChange}
        onClickItem={this.onClickItem}
        keyDown={this.keyDown}
        disabled={disabled}
        fFocused={inlinePicker && fFocused}
        fFloating={!inlinePicker}
        style={styleList}
        twoStageStyle={twoStageStyle}
        accentColor={accentColor}
      />
    );
  }

  // ==========================================
  // Event handlers
  // ==========================================
  registerTitleRef(c) {
    this.refTitle = c;
    this.props.registerOuterRef(c);
  }

  // If the menu is not focused, ignore it: it will be handled by the `input` HOC.
  // ...but if it is focused, we want to toggle it
  onMouseDownTitle() {
    if (!this.props.fFocused) return;
    this.setState({ fFloat: !this.state.fFloat });
  }

  onClickItem(ev, nextValue) {
    const { inlinePicker } = this.props;
    if (!inlinePicker) this.setState({ fFloat: false });
    this.props.onClickItem && this.props.onClickItem(ev, toExternalValue(nextValue));
  }

  // ==========================================
  // Helpers
  // ==========================================
  processKeyDown(keyDown) {
    if (keyDown.which === KEYS.esc && !this.props.inlinePicker) {
      this.setState({ fFloat: !this.state.fFloat });
      this.keyDown = undefined;
      return;
    }
    this.keyDown = keyDown;
  }

  prepareItems(rawItems, required) {
    this.items = [];
    if (!required && rawItems.length) {
      this.items.push({
        value: NULL_STRING,
        label: '',
        shortcuts: [],
      });
    }
    rawItems.forEach(item => {
      const { value } = item;
      if (value === LIST_SEPARATOR_KEY) {
        this.items.push({
          value: LIST_SEPARATOR_KEY,
          label: LIST_SEPARATOR_KEY,
          shortcuts: [],
        });
        return;
      }
      let keys = item.keys || [];
      if (!Array.isArray(keys)) keys = [keys];
      this.items.push(merge(item, {
        value: toInternalValue(value),
        shortcuts: keys.map(createShortcut),
      }));
    });
  }

  registerShortcuts() {
    this.items.forEach(item => item.shortcuts.forEach(shortcut => {
      registerShortcut(shortcut, ev => {
        this.props.onChange(ev, item.value);
        this.onClickItem(ev, item.value);
      });
    }));
  }

  unregisterShortcuts() {
    this.items.forEach(item => item.shortcuts.forEach(unregisterShortcut));
  }
}

// ==========================================
// Styles
// ==========================================
const style = {
  titleBase: flexContainer('row', inputReset({
    display: 'inline-flex',
    padding: '1px 2px',
    minWidth: 40,
    cursor: 'pointer',
    position: 'relative',
  })),
  title: ({ disabled, fFocused }) => {
    let out = style.titleBase;
    if (disabled) out = merge(out, INPUT_DISABLED);
    if (fFocused) out = merge(out, GLOW);
    return out;
  },
  caret: {
    marginLeft: 15,
    marginRight: 3,
    marginTop: 1,
  },
  providedTitleWrapperForIos: { position: 'relative' },
};

// ==========================================
// Public API
// ==========================================
const SelectCustom = input(SelectCustomBase, {
  toInternalValue, toExternalValue, isNull,
  fIncludeFocusCapture: true,
  trappedKeys: [
    KEYS.esc,
    // For ListPicker
    KEYS.down, KEYS.up,
    KEYS.home, KEYS.end,
    KEYS.return, KEYS.del, KEYS.backspace,
  ],
  className: 'giu-select-custom',
});

export {
  SelectCustom,
  LIST_SEPARATOR,
};
<commit_msg>Fix bug in CustomSelects where keyboard shortcuts were unregistered when props changed<commit_after>import React                from 'react';
import { merge }            from 'timm';
import { bindAll }          from '../gral/helpers';
import {
  COLORS, KEYS,
  UNICODE,
  NULL_STRING,
  IS_IOS,
}                           from '../gral/constants';
import {
  flexContainer, flexItem,
  GLOW,
  inputReset, INPUT_DISABLED,
}                           from '../gral/styles';
import {
  createShortcut,
  registerShortcut,
  unregisterShortcut,
}                           from '../gral/keys';
import input                from '../hocs/input';
import {
  ListPicker,
  LIST_SEPARATOR_KEY,
}                           from '../inputs/listPicker';
import IosFloatWrapper      from '../inputs/iosFloatWrapper';
import {
  floatAdd,
  floatDelete,
  floatUpdate,
  warnFloats,
}                           from '../components/floats';
import Icon                 from '../components/icon';

const LIST_SEPARATOR = {
  value: LIST_SEPARATOR_KEY,
  label: LIST_SEPARATOR_KEY,
};

function toInternalValue(val) { return val != null ? JSON.stringify(val) : NULL_STRING; }
function toExternalValue(val) { return val !== NULL_STRING ? JSON.parse(val) : null; }
function isNull(val) { return val === NULL_STRING; }

// ==========================================
// Component
// ==========================================
class SelectCustomBase extends React.Component {
  static propTypes = {
    disabled:               React.PropTypes.bool,
    items:                  React.PropTypes.array.isRequired,
    required:               React.PropTypes.bool,
    inlinePicker:           React.PropTypes.bool,
    children:               React.PropTypes.any,
    onClickItem:            React.PropTypes.func,
    onCloseFloat:           React.PropTypes.func,
    floatPosition:          React.PropTypes.string,
    floatAlign:             React.PropTypes.string,
    floatZ:                 React.PropTypes.number,
    style:                  React.PropTypes.object,
    twoStageStyle:          React.PropTypes.bool,
    accentColor:            React.PropTypes.string,
    // Input HOC
    curValue:               React.PropTypes.string.isRequired,
    onChange:               React.PropTypes.func.isRequired,
    registerOuterRef:       React.PropTypes.func.isRequired,
    fFocused:               React.PropTypes.bool.isRequired,
    keyDown:                React.PropTypes.object,
  };
  static defaultProps = {
    accentColor:            COLORS.accent,
  };

  constructor(props) {
    super(props);
    this.state = { fFloat: false };
    this.keyDown = undefined;
    bindAll(this, [
      'registerTitleRef',
      'onMouseDownTitle',
      'onClickItem',
    ]);
  }

  componentWillMount() {
    this.prepareItems(this.props.items, this.props.required);
  }

  componentDidMount() {
    if (!this.props.inlinePicker) {
      warnFloats(this.constructor.name);
    }
    this.registerShortcuts();
  }

  componentWillReceiveProps(nextProps) {
    const { keyDown, items, required, fFocused } = nextProps;
    if (keyDown !== this.props.keyDown) this.processKeyDown(keyDown);
    if (items !== this.props.items || required !== this.props.required) {
      this.prepareItems(items, required);
    }
    if (fFocused !== this.props.fFocused) {
      this.setState({ fFloat: fFocused });
    }
  }

  componentDidUpdate() {
    this.renderFloat();
  }

  componentWillUnmount() {
    floatDelete(this.floatId);
    this.unregisterShortcuts();
  }

  // ==========================================
  // Render
  // ==========================================
  render() {
    let out;
    if (this.props.inlinePicker) {
      out = this.renderPicker();
    } else if (this.props.children) {
      out = this.renderProvidedTitle();
    } else {
      out = this.renderDefaultTitle();
    }
    return out;
  }

  renderProvidedTitle() {
    const elTitle = React.cloneElement(this.props.children, {
      ref: this.registerTitleRef,
    });
    return IS_IOS ?

        {elTitle}
        {this.renderFloatForIos()}
       :
      elTitle;
  }

  renderDefaultTitle() {
    const { curValue } = this.props;
    let label = UNICODE.nbsp;
    if (curValue !== NULL_STRING) {
      for (let i = 0; i < this.items.length; i++) {
        if (this.items[i].value === curValue) {
          label = this.items[i].label;
          break;
        }
      }
    }
    const caretIcon = this.state.fFloat ? 'caret-up' : 'caret-down';
    return (

        {label}

        <Icon icon={caretIcon} style={style.caret} />
        {IS_IOS && this.renderFloatForIos()}

    );
  }

  renderFloat() {
    if (this.props.inlinePicker) return;
    if (IS_IOS) return;
    const { fFloat } = this.state;

    // Remove float
    if (!fFloat && this.floatId != null) {
      floatDelete(this.floatId);
      this.floatId = null;
      this.props.onCloseFloat && this.props.onCloseFloat();
      return;
    }

    // Create or update float
    if (fFloat) {
      const { floatZ, floatPosition, floatAlign } = this.props;
      const floatOptions = {
        position: floatPosition,
        align: floatAlign,
        zIndex: floatZ,
        limitSize: true,
        getAnchorNode: () => this.refTitle,
        children: this.renderPicker(),
      };
      if (this.floatId == null) {
        this.floatId = floatAdd(floatOptions);
      } else {
        floatUpdate(this.floatId, floatOptions);
      }
    }
  }

  renderFloatForIos() {
    if (!this.state.fFloat) return null;
    const { floatPosition, floatAlign, floatZ } = this.props;
    return (
      <IosFloatWrapper
        floatPosition={floatPosition}
        floatAlign={floatAlign}
        floatZ={floatZ}
      >
        {this.renderPicker()}
      </IosFloatWrapper>
    );
  }

  renderPicker() {
    const {
      inlinePicker,
      registerOuterRef,
      curValue, onChange,
      disabled, fFocused,
      style: styleList,
      twoStageStyle, accentColor,
    } = this.props;
    return (
      <ListPicker
        registerOuterRef={inlinePicker ? registerOuterRef : undefined}
        items={this.items}
        curValue={curValue}
        onChange={onChange}
        onClickItem={this.onClickItem}
        keyDown={this.keyDown}
        disabled={disabled}
        fFocused={inlinePicker && fFocused}
        fFloating={!inlinePicker}
        style={styleList}
        twoStageStyle={twoStageStyle}
        accentColor={accentColor}
      />
    );
  }

  // ==========================================
  // Event handlers
  // ==========================================
  registerTitleRef(c) {
    this.refTitle = c;
    this.props.registerOuterRef(c);
  }

  // If the menu is not focused, ignore it: it will be handled by the `input` HOC.
  // ...but if it is focused, we want to toggle it
  onMouseDownTitle() {
    if (!this.props.fFocused) return;
    this.setState({ fFloat: !this.state.fFloat });
  }

  onClickItem(ev, nextValue) {
    const { inlinePicker } = this.props;
    if (!inlinePicker) this.setState({ fFloat: false });
    this.props.onClickItem && this.props.onClickItem(ev, toExternalValue(nextValue));
  }

  // ==========================================
  // Helpers
  // ==========================================
  processKeyDown(keyDown) {
    if (keyDown.which === KEYS.esc && !this.props.inlinePicker) {
      this.setState({ fFloat: !this.state.fFloat });
      this.keyDown = undefined;
      return;
    }
    this.keyDown = keyDown;
  }

  prepareItems(rawItems, required) {
    this.items = [];
    if (!required && rawItems.length) {
      this.items.push({
        value: NULL_STRING,
        label: '',
        shortcuts: [],
      });
    }
    rawItems.forEach(item => {
      const { value } = item;
      if (value === LIST_SEPARATOR_KEY) {
        this.items.push({
          value: LIST_SEPARATOR_KEY,
          label: LIST_SEPARATOR_KEY,
          shortcuts: [],
        });
        return;
      }
      let keys = item.keys || [];
      if (!Array.isArray(keys)) keys = [keys];
      this.items.push(merge(item, {
        value: toInternalValue(value),
        shortcuts: keys.map(createShortcut),
      }));
    });
  }

  registerShortcuts() {
    this.items.forEach(item => item.shortcuts.forEach(shortcut => {
      registerShortcut(shortcut, ev => {
        this.props.onChange(ev, item.value);
        this.onClickItem(ev, item.value);
      });
    }));
  }

  unregisterShortcuts() {
    this.items.forEach(item => item.shortcuts.forEach(unregisterShortcut));
  }
}

// ==========================================
// Styles
// ==========================================
const style = {
  titleBase: flexContainer('row', inputReset({
    display: 'inline-flex',
    padding: '1px 2px',
    minWidth: 40,
    cursor: 'pointer',
    position: 'relative',
  })),
  title: ({ disabled, fFocused }) => {
    let out = style.titleBase;
    if (disabled) out = merge(out, INPUT_DISABLED);
    if (fFocused) out = merge(out, GLOW);
    return out;
  },
  caret: {
    marginLeft: 15,
    marginRight: 3,
    marginTop: 1,
  },
  providedTitleWrapperForIos: { position: 'relative' },
};

// ==========================================
// Public API
// ==========================================
const SelectCustom = input(SelectCustomBase, {
  toInternalValue, toExternalValue, isNull,
  fIncludeFocusCapture: true,
  trappedKeys: [
    KEYS.esc,
    // For ListPicker
    KEYS.down, KEYS.up,
    KEYS.home, KEYS.end,
    KEYS.return, KEYS.del, KEYS.backspace,
  ],
  className: 'giu-select-custom',
});

export {
  SelectCustom,
  LIST_SEPARATOR,
};
<|endoftext|>


<commit_before>'use strict'

import './styles.postcss';
import $ from 'jquery';
import Backbone from 'backbone';
import ProjectModel from './../../scripts/models/ProjectModel';
import PopUp from './PopUp';
import utils from '../../scripts/helpers/utils';

class PopUpProject extends PopUp {

  _getSectors() {
    let items = '';
    let i = 0;

    while( i < 3 ) {
      items = this.model.get('sectors')[i] && this.model.get('sectors')[i].name ? items + `<li class="sector text text-legend-s -light"> ${this.model.get('sectors')[i].name} </li>` : items + '';
      i++;
    }

    return `Sectors of interest

              ${items}

`
  }

  _getContent() {
    //TODO - we need percentage of reached people when filtering.
    const sectorsItems = (this.model.get('sectors').length > 0) ? this._getSectors() : '';

    return `

 ${this.model.get('location')['name']} - ${ utils.numberNotation(  this.model.get('totals')['projects'] )} projects

            ${ sectorsItems }

${ utils.numberNotation(this.model.get('totals')['people']) } People reached

${ utils.numberNotation(this.model.get('totals')['women_and_girls']) + '%' } Women & girls

            Explore country page
            <svg class="icon icon-externallink -light">
              <use xlink:href="#icon-externallink"></use>
            </svg>

`
  }
}

PopUpProject.prototype.model = new ProjectModel();

export default PopUpProject;

<commit_msg>Updates copy for projects tooltip as requested<commit_after>'use strict'

import './styles.postcss';
import $ from 'jquery';
import Backbone from 'backbone';
import ProjectModel from './../../scripts/models/ProjectModel';
import PopUp from './PopUp';
import utils from '../../scripts/helpers/utils';

class PopUpProject extends PopUp {

  _getSectors() {
    let items = '';
    let i = 0;

    while( i < 3 ) {
      items = this.model.get('sectors')[i] && this.model.get('sectors')[i].name ? items + `<li class="sector text text-legend-s -light"> ${this.model.get('sectors')[i].name} </li>` : items + '';
      i++;
    }

    return `Key Programme Sectors

              ${items}

`
  }

  _getContent() {
    //TODO - we need percentage of reached people when filtering.
    const sectorsItems = (this.model.get('sectors').length > 0) ? this._getSectors() : '';

    return `

 ${this.model.get('location')['name']} - ${ utils.numberNotation(  this.model.get('totals')['projects'] )} projects

            ${ sectorsItems }

${ utils.numberNotation(this.model.get('totals')['people']) } People reached

${ utils.numberNotation(this.model.get('totals')['women_and_girls']) + '%' } Women & girls

            Explore country page
            <svg class="icon icon-externallink -light">
              <use xlink:href="#icon-externallink"></use>
            </svg>

`
  }
}

PopUpProject.prototype.model = new ProjectModel();

export default PopUpProject;

<|endoftext|>


<commit_before>// @flow
/**
 * search for dom elements on your page
 * @module holmes
 */
(function (root, factory) {
  'use strict';

  /* $FlowIssue - doesn't work with umd */
  if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef
    // AMD. Register as an anonymous module.
    define([], function () { // eslint-disable-line no-undef
      /* $FlowIssue - doesn't work with umd */
      return (root.holmes = factory(document)); // eslint-disable-line no-undef, no-return-assign
    });
  } else if (typeof exports === 'object') { // eslint-disable-line no-undef
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory(document); // eslint-disable-line no-undef
  } else {
    // Browser globals
    /* $FlowIssue - doesn't work with umd */
    root.holmes = factory(document);
  }
})(this, function (document) {
  // UMD Definition above, do not remove this line

  // To get to know more about the Universal Module Definition
  // visit: https://github.com/umdjs/umd

  'use strict';

  /**
   * search for dom elements on your page
   * @alias module:holmes
   * @constructor
   * @param {string} [options.input='input[type=search]']
   *   A querySelector to find the input
   * @param {string} options.find
   *   A querySelectorAll rule to find each of the find terms
   * @param {string=} options.placeholder
   *   Text to show when there are no results (innerHTML)
   * @param {bool} [options.mark=false]
   *   Whether to <mark></mark> the matching text
   *   Text to show when there are no results (innerHTML)
   * @param {string} [options.class.visible=false]
   *   class to add to matched items
   * @param {string} [options.class.hidden='hidden']
   *   class to add to non-matched items
   * @param {boolean} [options.dynamic=false]
   *   Whether to query for the content of the elements on every input.
   *   If this is false, then only when initializing the script will
   *   fetch the content of the elements to search in. If this is true
   *   then it will refresh on every input event.
   * @param {boolean} [options.contenteditable=false]
   *   DEPRECATED (now handled automatically) whether the input is a contenteditable or
   *   not. By default it's assumed that it's <input>, true here
   *   will use <div contenteditable>
   * @param {boolean} [options.instant=false]
   *   By default Holmes waits for the DOMContentLoaded event to fire
   *   before listening. This is to make sure that all content is available. However
   *   if you exactly know when all your content is available (ajax, your own event or
   *   other situations), you can put this option on true.
   * @param {number} [options.minCharacters=0] The minimum amount of characters to be typed before
   *   Holmes starts searching. Beware that this also counts when backspacing.
   * @param {onChange} [options.onHidden]
   *   Callback for when an item is hidden.
   * @param {onChange} [options.onVisible]
   *   Callback for when an item is visible again.
   * @param {onChange} [options.onEmpty]
   *   Callback for when no items were found.
   * @param {onChange} [options.onFound]
   *   Callback for when items are found after being empty.
   * @param {function} [options.onInput]
   *   Callback for every input.
   */
  function holmes(options) {
    var empty = false;

    if (typeof options !== 'object') {
      throw new Error('The options need to be given inside an object like this:\nholmes({\n\tfind:".result"\n});\nsee also https://haroen.me/holmes/doc/module-holmes.html');
    }

    /**
     * Options
     * @type {Object}
     */
    holmes.prototype.options = options;

    // if holmes.prototype.options.find is missing, the searching won't work so we'll thrown an exceptions
    if (typeof holmes.prototype.options.find !== 'string') {
      throw new Error('A find argument is needed. That should be a querySelectorAll for each of the items you want to match individually. You should have something like: \nholmes({\n\tfind:".result"\n});\nsee also https://haroen.me/holmes/doc/module-holmes.html');
    }

    /**
     * Start an event listener with the specified options
     */
    holmes.prototype.start = function () {
      // setting default values
      if (typeof holmes.prototype.options.input !== 'string') {
        holmes.prototype.options.input = 'input[type=search]';
      }
      if (typeof holmes.prototype.options.placeholder !== 'string') {
        holmes.prototype.options.placeholder = false;
      }
      if (typeof holmes.prototype.options.mark !== 'boolean') {
        holmes.prototype.options.mark = false;
      }
      if (typeof holmes.prototype.options.class !== 'object') {
        holmes.prototype.options.class = {};
      }
      if (typeof holmes.prototype.options.class.visible !== 'string') {
        holmes.prototype.options.class.visible = false;
      }
      if (typeof holmes.prototype.options.class.hidden !== 'string') {
        holmes.prototype.options.class.hidden = 'hidden';
      }
      if (typeof holmes.prototype.options.dynamic !== 'boolean') {
        holmes.prototype.options.dynamic = false;
      }
      if (typeof holmes.prototype.options.minCharacters !== 'number') {
        holmes.prototype.options.minCharacters = 0;
      }

      holmes.prototype.running = true;

      /**
       * The input element
       * @type {NodeList}
       */
      holmes.prototype.input = document.querySelector(holmes.prototype.options.input);

      /**
       * All of the elements that are searched
       * @type {NodeList}
       */
      holmes.prototype.elements = document.querySelectorAll(holmes.prototype.options.find);

      /**
       * amount of elements to search
       * @type {Number}
       */
      holmes.prototype.elementsLength = holmes.prototype.elements.length;

      /**
       * all of the elements that are searched as an array
       * @type {Array}
       */
      holmes.prototype.elementsArray = Array.prototype.slice.call(holmes.prototype.elements);

      /**
       * The amount of elements that are hidden
       * @type {Number}
       */
      holmes.prototype.hidden = 0;

      // create a container for a placeholder
      if (holmes.prototype.options.placeholder) {
        /**
         * Placeholder element
         * @type {Element}
         */
        holmes.prototype.placeholder = document.createElement('div');
        holmes.prototype.placeholder.id = 'holmes-placeholder';
        holmes.prototype.placeholder.classList.add(holmes.prototype.options.class.hidden);
        holmes.prototype.placeholder.innerHTML = holmes.prototype.options.placeholder;
        if (holmes.prototype.elements[0].parentNode) {
          holmes.prototype.elements[0].parentNode.appendChild(holmes.prototype.placeholder);
        } else {
          throw new Error('The Holmes placeholder could\'t be put; the elements had no parent.');
        }
      }

      // if a visible class is given, give it to everything
      if (holmes.prototype.options.class.visible) {
        holmes.prototype.elementsArray.forEach(function (element) {
          element.classList.add(holmes.prototype.options.class.visible);
        });
      }

      // listen for input
      holmes.prototype.input.addEventListener('input', inputHandler);
    };

    /**
     * The current search input in lower case
     * @return {String} the input as a string
     */
    function inputString() {
      if (holmes.prototype.input instanceof HTMLInputElement) {
        return holmes.prototype.input.value.toLowerCase();
      }
      if (holmes.prototype.input.contentEditable) {
        return holmes.prototype.input.textContent.toLowerCase();
      }
      throw new Error('The Holmes input was no <input> or contenteditable.');
    }

    /**
     * hide an element
     * @param  {HTMLElement} element the element to hide
     */
    function hideElement(element) {
      if (holmes.prototype.options.class.visible) {
        element.classList.remove(holmes.prototype.options.class.visible);
      }
      if (!element.classList.contains(holmes.prototype.options.class.hidden)) {
        element.classList.add(holmes.prototype.options.class.hidden);
        holmes.prototype.hidden++;

        if (typeof holmes.prototype.options.onHidden === 'function') {
          holmes.prototype.options.onHidden(element);
        }
      }
      if (holmes.prototype.options.mark) {
        element.innerHTML = element.innerHTML.replace(/<\/?mark>/g, '');
      }
    }

    /**
     * show an element
     * @param  {HTMLElement} element the element to show
     */
    function showElement(element) {
      if (holmes.prototype.options.class.visible) {
        element.classList.add(holmes.prototype.options.class.visible);
      }
      if (element.classList.contains(holmes.prototype.options.class.hidden)) {
        element.classList.remove(holmes.prototype.options.class.hidden);
        holmes.prototype.hidden--;

        if (typeof holmes.prototype.options.onVisible === 'function') {
          holmes.prototype.options.onVisible(element);
        }
      }

      // if we need to mark it:
      // remove all  tags
      // add new  tags around the text
      if (holmes.prototype.options.mark) {
        element.innerHTML = element.innerHTML.replace(/<\/?mark>/g, '');
        if (holmes.prototype.searchString.length) {
          element.innerHTML = element.innerHTML.replace(holmes.prototype.regex, '$1');
        }
      }
    }

    /**
     * input event handler
     */
    function inputHandler() {
      // by default the value isn't found
      var found = false;

      /**
       * Lowercase string holmes searces for
       * @type {string}
       */
      holmes.prototype.searchString = inputString();

      // if a minimum of characters is required
      // check if that limit has been reached
      if (holmes.prototype.options.minCharacters) {
        if (holmes.prototype.searchString.length !== 0) {
          if (holmes.prototype.options.minCharacters > holmes.prototype.searchString.length) {
            return;
          }
        }
      }

      // if the dynamic option is enabled, then we should query
      // for the contents of `elements` on every input
      if (holmes.prototype.options.dynamic) {
        holmes.prototype.elements = document.querySelectorAll(holmes.prototype.options.find);
        holmes.prototype.elementsLength = holmes.prototype.elements.length;
        holmes.prototype.elementsArray = Array.prototype.slice.call(holmes.prototype.elements);
      }

      // loop over all the elements
      // in case this should become dynamic, query for the elements here
      holmes.prototype.regex = new RegExp('(' + holmes.prototype.searchString + ')(?![^<]*>)', 'gi');

      holmes.prototype.elementsArray.forEach(function (element) {
        // if the current element doesn't contain the search string
        // add the hidden class and remove the visbible class
        if (element.textContent.toLowerCase().indexOf(holmes.prototype.searchString) === -1) {
          hideElement(element);
        } else {
          showElement(element);

          if (empty && typeof holmes.prototype.options.onFound === 'function') {
            holmes.prototype.options.onFound(holmes.prototype.placeholder);
          }
          empty = false;
          // the element is now found at least once
          found = true;
        }
      });

      if (typeof holmes.prototype.options.onInput === 'function') {
        holmes.prototype.options.onInput(holmes.prototype.searchString);
      }

      // No results were found and last time we checked it wasn't empty
      if (!found && !empty) {
        empty = true;

        if (holmes.prototype.options.placeholder) {
          holmes.prototype.placeholder.classList.remove(holmes.prototype.options.class.hidden);
        }
        if (typeof holmes.prototype.options.onEmpty === 'function') {
          holmes.prototype.options.onEmpty(holmes.prototype.placeholder);
        }
      } else if (!empty) {
        if (holmes.prototype.options.placeholder) {
          holmes.prototype.placeholder.classList.add(holmes.prototype.options.class.hidden);
        }
      }
    }

    // whether to start immediately or wait on the load of DOMContent
    if (typeof holmes.prototype.options.instant !== 'boolean') {
      holmes.prototype.options.instant = false;
    }

    if (holmes.prototype.options.instant) {
      holmes.prototype.start();
    } else {
      window.addEventListener('DOMContentLoaded', holmes.prototype.start);
    }

    /**
     * remove the current event listener
     * @see holmes.prototype.start
     * @return {Promise} resolves when the event is removed
     */
    holmes.prototype.stop = function () {
      return new Promise(function (resolve, reject) {
        try {
          holmes.prototype.input.removeEventListener('input', inputHandler);

          // remove placeholder
          if (holmes.prototype.placeholder.parentNode) {
            holmes.prototype.placeholder.parentNode.removeChild(holmes.prototype.placeholder);
          } else {
            throw new Error('The Holmes placeholder has no parent.');
          }

          // remove marks
          if (holmes.prototype.options.mark) {
            holmes.prototype.elementsArray.forEach(function (element) {
              element.innerHTML = element.innerHTML.replace(/<\/?mark>/g, '');
            });
          }

          // done
          holmes.prototype.running = false;
          resolve('This instance of Holmes has been stopped.');
        } catch (err) {
          reject(err);
        }
      });
    };

    /**
     * empty the search string programmatically.
     * This avoids having to send a new `input` event
     */
    holmes.prototype.clear = function () {
      if (holmes.prototype.input instanceof HTMLInputElement) {
        holmes.prototype.input.value = '';
      } else if (holmes.prototype.input.contentEditable) {
        holmes.prototype.input.textContent = '';
      } else {
        throw new Error('The Holmes input was no <input> or contenteditable.');
      }
      // if a visible class is given, give it to everything
      if (holmes.prototype.options.class.visible) {
        holmes.prototype.elementsArray.forEach(function (element) {
          element.classList.remove(holmes.prototype.options.class.hidden);
          element.classList.add(holmes.prototype.options.class.visible);
        });
      } else {
        holmes.prototype.elementsArray.forEach(function (element) {
          element.classList.remove(holmes.prototype.options.class.hidden);
        });
      }
      if (holmes.prototype.options.placeholder) {
        holmes.prototype.placeholder.classList.add(holmes.prototype.options.class.hidden);
        if (holmes.prototype.options.class.visible) {
          holmes.prototype.placeholder.classList.remove(holmes.prototype.options.class.visible);
        }
      }

      holmes.prototype.hidden = 0;
    };

    /**
     * Show the amount of elements, and those hidden and visible
     * @return {object} all matching elements, the amount of hidden and the amount of visible elements
     */
    holmes.prototype.count = function () {
      return {
        all: holmes.prototype.elementsLength,
        hidden: holmes.prototype.hidden,
        visible: holmes.prototype.elementsLength - holmes.prototype.hidden
      };
    };
  }

  /**
   * Callback used for changes in item en list states.
   * @callback onChange
   * @param {object} [element]
   *   Element affected by the event. This is the item found by
   *   onVisible and onHidden and the placeholder
   *   (or undefined) for onEmpty and
   *   onFound.
   */

  return holmes;
});
<commit_msg>optimize<commit_after>// @flow
/**
 * search for dom elements on your page
 * @module holmes
 */
(function (root, factory) {
  'use strict';

  /* $FlowIssue - doesn't work with umd */
  if (typeof define === 'function' && define.amd) { // eslint-disable-line no-undef
    // AMD. Register as an anonymous module.
    define([], function () { // eslint-disable-line no-undef
      /* $FlowIssue - doesn't work with umd */
      return (root.holmes = factory(document)); // eslint-disable-line no-undef, no-return-assign
    });
  } else if (typeof exports === 'object') { // eslint-disable-line no-undef
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory(document); // eslint-disable-line no-undef
  } else {
    // Browser globals
    /* $FlowIssue - doesn't work with umd */
    root.holmes = factory(document);
  }
})(this, (function (document) {
  // UMD Definition above, do not remove this line

  // To get to know more about the Universal Module Definition
  // visit: https://github.com/umdjs/umd

  'use strict';

  /**
   * search for dom elements on your page
   * @alias module:holmes
   * @constructor
   * @param {string} [options.input='input[type=search]']
   *   A querySelector to find the input
   * @param {string} options.find
   *   A querySelectorAll rule to find each of the find terms
   * @param {string=} options.placeholder
   *   Text to show when there are no results (innerHTML)
   * @param {bool} [options.mark=false]
   *   Whether to <mark></mark> the matching text
   *   Text to show when there are no results (innerHTML)
   * @param {string} [options.class.visible=false]
   *   class to add to matched items
   * @param {string} [options.class.hidden='hidden']
   *   class to add to non-matched items
   * @param {boolean} [options.dynamic=false]
   *   Whether to query for the content of the elements on every input.
   *   If this is false, then only when initializing the script will
   *   fetch the content of the elements to search in. If this is true
   *   then it will refresh on every input event.
   * @param {boolean} [options.contenteditable=false]
   *   DEPRECATED (now handled automatically) whether the input is a contenteditable or
   *   not. By default it's assumed that it's <input>, true here
   *   will use <div contenteditable>
   * @param {boolean} [options.instant=false]
   *   By default Holmes waits for the DOMContentLoaded event to fire
   *   before listening. This is to make sure that all content is available. However
   *   if you exactly know when all your content is available (ajax, your own event or
   *   other situations), you can put this option on true.
   * @param {number} [options.minCharacters=0] The minimum amount of characters to be typed before
   *   Holmes starts searching. Beware that this also counts when backspacing.
   * @param {onChange} [options.onHidden]
   *   Callback for when an item is hidden.
   * @param {onChange} [options.onVisible]
   *   Callback for when an item is visible again.
   * @param {onChange} [options.onEmpty]
   *   Callback for when no items were found.
   * @param {onChange} [options.onFound]
   *   Callback for when items are found after being empty.
   * @param {function} [options.onInput]
   *   Callback for every input.
   */
  function holmes(options) {
    var empty = false;

    if (typeof options !== 'object') {
      throw new Error('The options need to be given inside an object like this:\nholmes({\n\tfind:".result"\n});\nsee also https://haroen.me/holmes/doc/module-holmes.html');
    }

    /**
     * Options
     * @type {Object}
     */
    holmes.prototype.options = {
      input: 'input[type=search]',
      placeholder: '',
      placeholderNode: null,
      mark: false,
      class: {
        visible: '',
        hidden: 'hidden'
      },
      dynamic: false,
      minCharacters: 0,
      find: ''
    };

    // if holmes.prototype.options.find is missing, the searching won't work so we'll thrown an exceptions
    if (typeof holmes.prototype.options.find !== 'string') {
      throw new Error('A find argument is needed. That should be a querySelectorAll for each of the items you want to match individually. You should have something like: \nholmes({\n\tfind:".result"\n});\nsee also https://haroen.me/holmes/doc/module-holmes.html');
    }

    holmes.prototype.mergeObj = function (Obj1, Obj2) {
      var k;
      for(k in Obj2){
        if(Obj1.hasOwnProperty(k) && (typeof Obj2[k] === typeof Obj1[k])){
          if(typeof Obj2[k] === 'object'){
            holmes.prototype.mergeObj(Obj1[k], Obj2[k]);
          }else{
            Obj1[k] = Obj2[k];
          }
        }
      }
    };

    /**
     * Start an event listener with the specified options
     */
    holmes.prototype.start = function (options) {
      // setting default values
      holmes.prototype.mergeObj(holmes.prototype.options, options);

      holmes.prototype.running = true;

      /**
       * The input element
       * @type {NodeList}
       */
      holmes.prototype.input = document.querySelector(holmes.prototype.options.input);

      /**
       * All of the elements that are searched
       * @type {NodeList}
       */
      holmes.prototype.elements = document.querySelectorAll(holmes.prototype.options.find);

      /**
       * amount of elements to search
       * @type {Number}
       */
      holmes.prototype.elementsLength = holmes.prototype.elements.length;

      /**
       * all of the elements that are searched as an array
       * @type {Array}
       */
      holmes.prototype.elementsArray = Array.prototype.slice.call(holmes.prototype.elements);

      /**
       * The amount of elements that are hidden
       * @type {Number}
       */
      holmes.prototype.hidden = 0;

      // create a container for a placeholder
      if (holmes.prototype.options.placeholder) {
        /**
         * Placeholder element
         * @type {Element}
         */
        holmes.prototype.placeholderNode = document.createElement('div');
        holmes.prototype.placeholderNode.id = 'holmes-placeholder';
        holmes.prototype.placeholderNode.classList.add(holmes.prototype.options.class.hidden);
        holmes.prototype.placeholderNode.innerHTML = holmes.prototype.options.placeholder;
        if (holmes.prototype.elements[0].parentNode) {
          holmes.prototype.elements[0].parentNode.appendChild(holmes.prototype.placeholderNode);
        } else {
          throw new Error('The Holmes placeholder could\'t be put; the elements had no parent.');
        }
      }

      // if a visible class is given, give it to everything
      if (holmes.prototype.options.class.visible) {
        holmes.prototype.elementsArray.forEach((function (element) {
          element.classList.add(holmes.prototype.options.class.visible);
        }));
      }

      // listen for input
      holmes.prototype.input.addEventListener('input', inputHandler);
    };

    /**
     * The current search input in lower case
     * @return {String} the input as a string
     */
    function inputString() {
      if (holmes.prototype.input instanceof HTMLInputElement) {
        return holmes.prototype.input.value.toLowerCase();
      }
      if (holmes.prototype.input.contentEditable) {
        return holmes.prototype.input.textContent.toLowerCase();
      }
      throw new Error('The Holmes input was no <input> or contenteditable.');
    }

    /**
     * hide an element
     * @param  {HTMLElement} element the element to hide
     */
    function hideElement(element) {
      if (holmes.prototype.options.class.visible) {
        element.classList.remove(holmes.prototype.options.class.visible);
      }
      if (!element.classList.contains(holmes.prototype.options.class.hidden)) {
        element.classList.add(holmes.prototype.options.class.hidden);
        holmes.prototype.hidden++;

        if (typeof holmes.prototype.options.onHidden === 'function') {
          holmes.prototype.options.onHidden(element);
        }
      }
      if (holmes.prototype.options.mark) {
        element.innerHTML = element.innerHTML.replace(/<\/?mark>/g, '');
      }
    }

    /**
     * show an element
     * @param  {HTMLElement} element the element to show
     */
    function showElement(element) {
      if (holmes.prototype.options.class.visible) {
        element.classList.add(holmes.prototype.options.class.visible);
      }
      if (element.classList.contains(holmes.prototype.options.class.hidden)) {
        element.classList.remove(holmes.prototype.options.class.hidden);
        holmes.prototype.hidden--;

        if (typeof holmes.prototype.options.onVisible === 'function') {
          holmes.prototype.options.onVisible(element);
        }
      }

      // if we need to mark it:
      // remove all  tags
      // add new  tags around the text
      if (holmes.prototype.options.mark) {
        element.innerHTML = element.innerHTML.replace(/<\/?mark>/g, '');
        if (holmes.prototype.searchString.length) {
          element.innerHTML = element.innerHTML.replace(holmes.prototype.regex, '$1');
        }
      }
    }

    /**
     * input event handler
     */
    function inputHandler() {
      // by default the value isn't found
      var found = false;

      /**
       * Lowercase string holmes searces for
       * @type {string}
       */
      holmes.prototype.searchString = inputString();

      // if a minimum of characters is required
      // check if that limit has been reached
      if (holmes.prototype.options.minCharacters) {
        if (holmes.prototype.searchString.length !== 0) {
          if (holmes.prototype.options.minCharacters > holmes.prototype.searchString.length) {
            return;
          }
        }
      }

      // if the dynamic option is enabled, then we should query
      // for the contents of `elements` on every input
      if (holmes.prototype.options.dynamic) {
        holmes.prototype.elements = document.querySelectorAll(holmes.prototype.options.find);
        holmes.prototype.elementsLength = holmes.prototype.elements.length;
        holmes.prototype.elementsArray = Array.prototype.slice.call(holmes.prototype.elements);
      }

      // loop over all the elements
      // in case this should become dynamic, query for the elements here
      if (holmes.prototype.options.mark) {
        holmes.prototype.regex = new RegExp('(' + holmes.prototype.searchString + ')(?![^<]*>)', 'gi');
      }

      holmes.prototype.elementsArray.forEach((function (element) {
        // still typing
        if(holmes.prototype.searchString.indexOf(holmes.prototype.prevValue) !== -1){
          if (element.classList.contains(holmes.prototype.options.class.hidden)) return;
        }
        // if the current element doesn't contain the search string
        // add the hidden class and remove the visbible class
        if (element.textContent.toLowerCase().indexOf(holmes.prototype.searchString) === -1) {
          hideElement(element);
        } else {
          showElement(element);

          if (empty && typeof holmes.prototype.options.onFound === 'function') {
            holmes.prototype.options.onFound(holmes.prototype.placeholderNode);
          }
          empty = false;
          // the element is now found at least once
          found = true;
        }
      }));

      if (typeof holmes.prototype.options.onInput === 'function') {
        holmes.prototype.options.onInput(holmes.prototype.searchString);
      }

      // No results were found and last time we checked it wasn't empty
      if (!found && !empty) {
        empty = true;

        if (holmes.prototype.options.placeholderNode) {
          holmes.prototype.placeholderNode.classList.remove(holmes.prototype.options.class.hidden);
        }
        if (typeof holmes.prototype.options.onEmpty === 'function') {
          holmes.prototype.options.onEmpty(holmes.prototype.placeholderNode);
        }
      } else if (!empty) {
        if (holmes.prototype.options.placeholderNode) {
          holmes.prototype.placeholderNode.classList.add(holmes.prototype.options.class.hidden);
        }
      }

      holmes.prototype.prevValue = holmes.prototype.searchString;
    }

    // whether to start immediately or wait on the load of DOMContent
    if (typeof holmes.prototype.options.instant !== 'boolean') {
      holmes.prototype.options.instant = false;
    }

    if (holmes.prototype.options.instant) {
      holmes.prototype.start(options);
    } else {
      window.addEventListener('DOMContentLoaded', function(){
        holmes.prototype.start(options);
      });
    }

    /**
     * remove the current event listener
     * @see holmes.prototype.start
     * @return {Promise} resolves when the event is removed
     */
    holmes.prototype.stop = function () {
      return new Promise(function (resolve, reject) {
        try {
          holmes.prototype.input.removeEventListener('input', inputHandler);

          // remove placeholderNode
          if (holmes.prototype.placeholderNode.parentNode) {
            holmes.prototype.placeholderNode.parentNode.removeChild(holmes.prototype.placeholderNode);
          } else {
            throw new Error('The Holmes placeholderNode has no parent.');
          }

          // remove marks
          if (holmes.prototype.options.mark) {
            holmes.prototype.elementsArray.forEach(function (element) {
              element.innerHTML = element.innerHTML.replace(/<\/?mark>/g, '');
            });
          }

          // done
          holmes.prototype.running = false;
          resolve('This instance of Holmes has been stopped.');
        } catch (err) {
          reject(err);
        }
      });
    };

    /**
     * empty the search string programmatically.
     * This avoids having to send a new `input` event
     */
    holmes.prototype.clear = function () {
      if (holmes.prototype.input instanceof HTMLInputElement) {
        holmes.prototype.input.value = '';
      } else if (holmes.prototype.input.contentEditable) {
        holmes.prototype.input.textContent = '';
      } else {
        throw new Error('The Holmes input was no <input> or contenteditable.');
      }
      // if a visible class is given, give it to everything
      if (holmes.prototype.options.class.visible) {
        holmes.prototype.elementsArray.forEach(function (element) {
          element.classList.remove(holmes.prototype.options.class.hidden);
          element.classList.add(holmes.prototype.options.class.visible);
        });
      } else {
        holmes.prototype.elementsArray.forEach(function (element) {
          element.classList.remove(holmes.prototype.options.class.hidden);
        });
      }
      if (holmes.prototype.options.placeholderNode) {
        holmes.prototype.placeholderNode.classList.add(holmes.prototype.options.class.hidden);
        if (holmes.prototype.options.class.visible) {
          holmes.prototype.placeholderNode.classList.remove(holmes.prototype.options.class.visible);
        }
      }

      holmes.prototype.hidden = 0;
    };

    /**
     * Show the amount of elements, and those hidden and visible
     * @return {object} all matching elements, the amount of hidden and the amount of visible elements
     */
    holmes.prototype.count = function () {
      return {
        all: holmes.prototype.elementsLength,
        hidden: holmes.prototype.hidden,
        visible: holmes.prototype.elementsLength - holmes.prototype.hidden
      };
    };
  }

  /**
   * Callback used for changes in item en list states.
   * @callback onChange
   * @param {object} [element]
   *   Element affected by the event. This is the item found by
   *   onVisible and onHidden and the placeholder
   *   (or undefined) for onEmpty and
   *   onFound.
   */

  return holmes;
}));
<|endoftext|>


<commit_before>var db,rdb, dbPath = document.location.protocol+"//"+document.location.host+"/"+document.location.pathname.split("/")[1];
Pouch("idb://couch-leaf",function(e1,db1){
    if(!e1){
        db=db1;
        db.changes({continuous:true,onChange:docChange,include_docs:true},pass);
        Pouch(dbPath,function(e2,db2){
             if(!e2){
                rdb=db2;
                db.replicate.to(rdb,{continuous:true});
                rdb.changes({continuous:true,onChange:rdocChange,include_docs:true},pass);
            }
        });
    }
});
var m= L.map('map').setView([39.40, -96.42], 4),
	mq=L.tileLayer("http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpeg", {attribution:'Tiles Courtesy of MapQuest — Map data © OpenStreetMap contributors', subdomains:'1234'}).addTo(m),
	h = new L.Hash(m),
	d = new L.Control.Draw().addTo(m),
	drawnStuff = L.geoJson("",{pointToLayer:pointToLayer,onEachFeature:popUp}).addTo(m),
	allStuff = L.geoJson("",{pointToLayer:pointToLayer,onEachFeature:popUp})
	m.on('drawn', function (e) {
			doStuff(e.feature);
		});

function redoJson(){
		allStuff.clearLayers();
		allStuff.addUrl(document.location.protocol+"//"+document.location.host+"/"+document.location.pathname.split("/")[1]+"/"+document.location.pathname.split("/")[2]+"/"+document.location.pathname.split("/")[3]+"/_spatial/_list/geojson/all?bbox="+m.getBounds().toBBoxString());
		};

//m.on("moveend", redoJson);

var baseMaps = {
    "Map Quest": mq
    }, overlayMaps = {
	"Drawn Layers":drawnStuff,
	"All Layers":allStuff
	},lc=L.control.layers(baseMaps, overlayMaps).addTo(m);

function doStuff(data){
	db.post(data);
}

function pointToLayer(f,l){
	if(f.properties.radius){
		return L.circle(l, f.properties.radius);
	}else{
		return L.marker(l);
	}
}
function popUp(f,l){
    var out = [];
    if (f.properties){
        for(var key in f.properties){
            	out.push(key+": "+f.properties[key] + " x");
        }
        l.bindPopup("
"+out.join("
")+"

<input type='button' value='Add Row' id='addRow'><input type='button' value='delete' id='deleteDoc'>");
    }
}
function popU(f,l){
    var out = [];
    if (f.properties){
        for(var key in f.properties){
                out.push(key+": "+f.properties[key]);
        }
        l.bindPopup(out.join("
"));
    }
}
function docChange(c){
var doc = c.doc;
if(doc._rev.slice(0,1)==1&&"geometry" in doc){
drawnStuff.addData(doc);
}else if(doc._rev.slice(0,1)>1){
    delId(drawnStuff,doc._id);
    if(!doc._deleted&&"geometry" in doc){
    drawnStuff.addData(doc);
}
}
}
function rdocChange(c){
var doc = c.doc;
if(doc._rev.slice(0,1)==1&&"geometry" in doc){
allStuff.addData(doc);
}else if(doc._rev.slice(0,1)>1){
    delId(allStuff,doc._id);
    if(!doc._deleted&&"geometry" in doc){
    allStuff.addData(doc);
}
}
}
function delId(layer,id){
layer.eachLayer(function(f){
if(f.feature._id===id){
layer.removeLayer(f);
}
})}
var ee,eee,dd;
m.on("popupopen",function(e){
    var tdb;
    if(e.popup._source._leaflet_id in drawnStuff._layers){
        tdb = db;
    }else if(e.popup._source._leaflet_id in allStuff._layers){
        tdb = rdb;
    }
    var id = e.popup._source.feature._id;
    eee=id;
    L.DomEvent.addListener(L.DomUtil.get("deleteDoc"),"click",function(click){
        tdb.get(id, function(err, doc) {
            tdb.remove(doc, pass);
        });
    });
    L.DomEvent.addListener(L.DomUtil.get("addRow"),"click",function(click){
        var div =L.DomUtil.get(id);
        var form = L.DomUtil.create("form","row-form");
        form.id="addRowForm";
      var kInput =  L.DomUtil.create("input","k-input");
      kInput.setAttribute("style","width:4em");kInput.setAttribute("placeholder","key");

      var vInput =  L.DomUtil.create("input","v-input");
      vInput.setAttribute("style","width:4em");vInput.setAttribute("placeholder","value");
      form.appendChild(kInput);
      form.appendChild(vInput);
      var sub = L.DomUtil.create("input","sub-input");
      sub.setAttribute("type","submit");
      sub.setAttribute("value","save");
      form.appendChild(sub);
      form.onsubmit=function(e){

        var key = e.target[0].value;
        var value = e.target[1].value
        tdb.get(id,function(err,dc){
            tdb.properties[key]=value;
            tdb.post(dc);
            })
        return false;
        };
      div.appendChild(form);

    });
    $(".delete-row").click(function(e){ //almost did this without jquery
    ee=e;
        var key = e.currentTarget.id.slice(4)
        tdb.get(id,function(err,dc){
            dd=dc;
            delete dc.properties[key]
            tdb.post(dc);
            })
        });
});
function pass(){}
<commit_msg>got rid of some dead stuff<commit_after>var db,rdb, dbPath = document.location.protocol+"//"+document.location.host+"/"+document.location.pathname.split("/")[1];
Pouch("idb://couch-leaf",function(e1,db1){
    if(!e1){
        db=db1;
        db.changes({continuous:true,onChange:docChange,include_docs:true},pass);
        Pouch(dbPath,function(e2,db2){
             if(!e2){
                rdb=db2;
                db.replicate.to(rdb,{continuous:true});
                rdb.changes({continuous:true,onChange:rdocChange,include_docs:true},pass);
            }
        });
    }
});
var m= L.map('map').setView([39.40, -96.42], 4),
	mq=L.tileLayer("http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpeg", {attribution:'Tiles Courtesy of MapQuest — Map data © OpenStreetMap contributors', subdomains:'1234'}).addTo(m),
	h = new L.Hash(m),
	d = new L.Control.Draw().addTo(m),
	drawnStuff = L.geoJson("",{pointToLayer:pointToLayer,onEachFeature:popUp}).addTo(m),
	allStuff = L.geoJson("",{pointToLayer:pointToLayer,onEachFeature:popUp})
	m.on('drawn', function (e) {
			doStuff(e.feature);
		});

var baseMaps = {
    "Map Quest": mq
    }, overlayMaps = {
	"Drawn Layers":drawnStuff,
	"All Layers":allStuff
	},lc=L.control.layers(baseMaps, overlayMaps).addTo(m);

function doStuff(data){
	db.post(data);
}

function pointToLayer(f,l){
	if(f.properties.radius){
		return L.circle(l, f.properties.radius);
	}else{
		return L.marker(l);
	}
}
function popUp(f,l){
    var out = [];
    if (f.properties){
        for(var key in f.properties){
            	out.push(key+": "+f.properties[key] + " x");
        }
        l.bindPopup("
"+out.join("
")+"

<input type='button' value='Add Row' id='addRow'><input type='button' value='delete' id='deleteDoc'>");
    }
}
function docChange(c){
var doc = c.doc;
if(doc._rev.slice(0,1)==1&&"geometry" in doc){
drawnStuff.addData(doc);
}else if(doc._rev.slice(0,1)>1){
    delId(drawnStuff,doc._id);
    if(!doc._deleted&&"geometry" in doc){
    drawnStuff.addData(doc);
}
}
}
function rdocChange(c){
var doc = c.doc;
if(doc._rev.slice(0,1)==1&&"geometry" in doc){
allStuff.addData(doc);
}else if(doc._rev.slice(0,1)>1){
    delId(allStuff,doc._id);
    if(!doc._deleted&&"geometry" in doc){
    allStuff.addData(doc);
}
}
}
function delId(layer,id){
layer.eachLayer(function(f){
if(f.feature._id===id){
layer.removeLayer(f);
}
})}
var ee,eee,dd;
m.on("popupopen",function(e){
    var tdb;
    if(e.popup._source._leaflet_id in drawnStuff._layers){
        tdb = db;
    }else if(e.popup._source._leaflet_id in allStuff._layers){
        tdb = rdb;
    }
    var id = e.popup._source.feature._id;
    eee=id;
    L.DomEvent.addListener(L.DomUtil.get("deleteDoc"),"click",function(click){
        tdb.get(id, function(err, doc) {
            tdb.remove(doc, pass);
        });
    });
    L.DomEvent.addListener(L.DomUtil.get("addRow"),"click",function(click){
        var div =L.DomUtil.get(id);
        var form = L.DomUtil.create("form","row-form");
        form.id="addRowForm";
      var kInput =  L.DomUtil.create("input","k-input");
      kInput.setAttribute("style","width:4em");kInput.setAttribute("placeholder","key");

      var vInput =  L.DomUtil.create("input","v-input");
      vInput.setAttribute("style","width:4em");vInput.setAttribute("placeholder","value");
      form.appendChild(kInput);
      form.appendChild(vInput);
      var sub = L.DomUtil.create("input","sub-input");
      sub.setAttribute("type","submit");
      sub.setAttribute("value","save");
      form.appendChild(sub);
      form.onsubmit=function(e){

        var key = e.target[0].value;
        var value = e.target[1].value
        tdb.get(id,function(err,dc){
            tdb.properties[key]=value;
            tdb.post(dc);
            })
        return false;
        };
      div.appendChild(form);

    });
    $(".delete-row").click(function(e){ //almost did this without jquery
    ee=e;
        var key = e.currentTarget.id.slice(4)
        tdb.get(id,function(err,dc){
            dd=dc;
            delete dc.properties[key]
            tdb.post(dc);
            })
        });
});
function pass(){}
<|endoftext|>