<commit_before>import React, {PropTypes} from 'react';
import LayoutRenderer from 'shared/components/LayoutRenderer';
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
import ReactTooltip from 'react-tooltip';
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
import {getMappings, getAppsForHosts, getMeasurementsForHost, getAllHosts} from 'src/hosts/apis';
import {fetchLayouts} from 'shared/apis';

export const HostPage = React.createClass({
  propTypes: {
    source: PropTypes.shape({
      links: PropTypes.shape({
        proxy: PropTypes.string.isRequired,
      }).isRequired,
      telegraf: PropTypes.string.isRequired,
      id: PropTypes.string.isRequired,
    }),
    params: PropTypes.shape({
      hostID: PropTypes.string.isRequired,
    }).isRequired,
    location: PropTypes.shape({
      query: PropTypes.shape({
        app: PropTypes.string,
      }),
    }),
  },

  getInitialState() {
    const fifteenMinutesIndex = 1;

    return {
      layouts: [],
      hosts: [],
      timeRange: timeRanges[fifteenMinutesIndex],
    };
  },

  componentDidMount() {
    const {source, params, location} = this.props;

    // fetching layouts and mappings can be done at the same time
    fetchLayouts().then(({data: {layouts}}) => {
      getMappings().then(({data: {mappings}}) => {
        getAllHosts(source.links.proxy, source.telegraf).then((hosts) => {
          getAppsForHosts(source.links.proxy, hosts, mappings, source.telegraf).then((newHosts) => {
            getMeasurementsForHost(source, params.hostID).then((measurements) => {
              const host = newHosts[this.props.params.hostID];
              const filteredLayouts = layouts.filter((layout) => {
                const focusedApp = location.query.app;
                if (focusedApp) {
                  return layout.app === focusedApp;
                }

                return host.apps && host.apps.includes(layout.app) && measurements.includes(layout.measurement);
              });
              this.setState({layouts: filteredLayouts, hosts});
            });
          });
        });
      });
    });
  },

  handleChooseTimeRange({lower}) {
    const timeRange = timeRanges.find((range) => range.queryValue === lower);
    this.setState({timeRange});
  },

  renderLayouts(layouts) {
    const autoRefreshMs = 15000;
    const {timeRange} = this.state;
    const {source} = this.props;

    const autoflowLayouts = layouts.filter((layout) => !!layout.autoflow);

    const cellWidth = 4;
    const cellHeight = 4;
    const pageWidth = 12;

    const autoflowCells = autoflowLayouts.reduce((allCells, layout, i) => {
      return allCells.concat(layout.cells.map((cell, j) => {
        return Object.assign(cell, {
          w: cellWidth,
          h: cellHeight,
          x: ((i + j) * cellWidth % pageWidth),
          y: Math.floor(((i + j) * cellWidth / pageWidth)) * cellHeight,
        });
      }));
    }, []);

    const staticLayouts = layouts.filter((layout) => !layout.autoflow);
    staticLayouts.unshift({cells: autoflowCells});

    let translateY = 0;
    const layoutCells = staticLayouts.reduce((allCells, layout) => {
      let maxY = 0;
      layout.cells.forEach((cell) => {
        cell.y += translateY;
        if (cell.y > translateY) {
          maxY = cell.y;
        }
        cell.queries.forEach((q) => {
          q.text = q.query;
          q.database = source.telegraf;
        });
      });
      translateY = maxY;

      return allCells.concat(layout.cells);
    }, []);

    return (
      <LayoutRenderer
        timeRange={timeRange}
        cells={layoutCells}
        autoRefreshMs={autoRefreshMs}
        source={source.links.proxy}
        host={this.props.params.hostID}
      />
    );
  },

  render() {
    const hostID = this.props.params.hostID;
    const {layouts, timeRange, hosts} = this.state;

    return (

                <button className="dropdown-toggle" type="button" data-toggle="dropdown">
                  {hostID}

                </button>

                  {Object.keys(hosts).map((host, i) => {
                    return (

                        <a href={`/sources/${this.props.source.id}/hosts/${host}`} className="role-option">
                          {host}

                    );
                  })}

              <div className="btn btn-info btn-sm" data-for="graph-tips-tooltip" data-tip="
Click + Drag Zoom in (X or Y)

Shift + Click Pan Graph Window

Double Click Reset Graph Window
">

                Graph Tips

              <ReactTooltip id="graph-tips-tooltip" effect="solid" html={true} offset={{top: 2}} place="bottom" class="influx-tooltip place-bottom" />
              <TimeRangeDropdown onChooseTimeRange={this.handleChooseTimeRange} selected={timeRange.inputValue} />

            { (layouts.length > 0) ? this.renderLayouts(layouts) : '' }

    );
  },
});

export default HostPage;
<commit_msg>filter out hosts that don't match the current app<commit_after>import React, {PropTypes} from 'react';
import LayoutRenderer from 'shared/components/LayoutRenderer';
import TimeRangeDropdown from '../../shared/components/TimeRangeDropdown';
import ReactTooltip from 'react-tooltip';
import timeRanges from 'hson!../../shared/data/timeRanges.hson';
import {getMappings, getAppsForHosts, getMeasurementsForHost, getAllHosts} from 'src/hosts/apis';
import {fetchLayouts} from 'shared/apis';
import _ from 'lodash';

export const HostPage = React.createClass({
  propTypes: {
    source: PropTypes.shape({
      links: PropTypes.shape({
        proxy: PropTypes.string.isRequired,
      }).isRequired,
      telegraf: PropTypes.string.isRequired,
      id: PropTypes.string.isRequired,
    }),
    params: PropTypes.shape({
      hostID: PropTypes.string.isRequired,
    }).isRequired,
    location: PropTypes.shape({
      query: PropTypes.shape({
        app: PropTypes.string,
      }),
    }),
  },

  getInitialState() {
    const fifteenMinutesIndex = 1;

    return {
      layouts: [],
      hosts: [],
      timeRange: timeRanges[fifteenMinutesIndex],
    };
  },

  componentDidMount() {
    const {source, params, location} = this.props;

    // fetching layouts and mappings can be done at the same time
    fetchLayouts().then(({data: {layouts}}) => {
      getMappings().then(({data: {mappings}}) => {
        getAllHosts(source.links.proxy, source.telegraf).then((hosts) => {
          getAppsForHosts(source.links.proxy, hosts, mappings, source.telegraf).then((newHosts) => {
            getMeasurementsForHost(source, params.hostID).then((measurements) => {
              const host = newHosts[this.props.params.hostID];
              const focusedApp = location.query.app;

              const filteredLayouts = layouts.filter((layout) => {
                if (focusedApp) {
                  return layout.app === focusedApp;
                }

                return host.apps && host.apps.includes(layout.app) && measurements.includes(layout.measurement);
              });

              // only display hosts in the list if they match the current app
              let filteredHosts = hosts;
              if (focusedApp) {
                filteredHosts = _.pickBy(hosts, (val, __, ___) => {
                  return val.apps.includes(focusedApp);
                });
              }
              this.setState({layouts: filteredLayouts, hosts: filteredHosts});
            });
          });
        });
      });
    });
  },

  handleChooseTimeRange({lower}) {
    const timeRange = timeRanges.find((range) => range.queryValue === lower);
    this.setState({timeRange});
  },

  renderLayouts(layouts) {
    const autoRefreshMs = 15000;
    const {timeRange} = this.state;
    const {source} = this.props;

    const autoflowLayouts = layouts.filter((layout) => !!layout.autoflow);

    const cellWidth = 4;
    const cellHeight = 4;
    const pageWidth = 12;

    const autoflowCells = autoflowLayouts.reduce((allCells, layout, i) => {
      return allCells.concat(layout.cells.map((cell, j) => {
        return Object.assign(cell, {
          w: cellWidth,
          h: cellHeight,
          x: ((i + j) * cellWidth % pageWidth),
          y: Math.floor(((i + j) * cellWidth / pageWidth)) * cellHeight,
        });
      }));
    }, []);

    const staticLayouts = layouts.filter((layout) => !layout.autoflow);
    staticLayouts.unshift({cells: autoflowCells});

    let translateY = 0;
    const layoutCells = staticLayouts.reduce((allCells, layout) => {
      let maxY = 0;
      layout.cells.forEach((cell) => {
        cell.y += translateY;
        if (cell.y > translateY) {
          maxY = cell.y;
        }
        cell.queries.forEach((q) => {
          q.text = q.query;
          q.database = source.telegraf;
        });
      });
      translateY = maxY;

      return allCells.concat(layout.cells);
    }, []);

    return (
      <LayoutRenderer
        timeRange={timeRange}
        cells={layoutCells}
        autoRefreshMs={autoRefreshMs}
        source={source.links.proxy}
        host={this.props.params.hostID}
      />
    );
  },

  render() {
    const hostID = this.props.params.hostID;
    const {layouts, timeRange, hosts} = this.state;
    const appParam = this.props.location.query.app ? `?app=${this.props.location.query.app}` : '';

    return (

                <button className="dropdown-toggle" type="button" data-toggle="dropdown">
                  {hostID}

                </button>

                  {Object.keys(hosts).map((host, i) => {
                    return (

                        <a href={`/sources/${this.props.source.id}/hosts/${host + appParam}`} className="role-option">
                          {host}

                    );
                  })}

              <div className="btn btn-info btn-sm" data-for="graph-tips-tooltip" data-tip="
Click + Drag Zoom in (X or Y)

Shift + Click Pan Graph Window

Double Click Reset Graph Window
">

                Graph Tips

              <ReactTooltip id="graph-tips-tooltip" effect="solid" html={true} offset={{top: 2}} place="bottom" class="influx-tooltip place-bottom" />
              <TimeRangeDropdown onChooseTimeRange={this.handleChooseTimeRange} selected={timeRange.inputValue} />

            { (layouts.length > 0) ? this.renderLayouts(layouts) : '' }

    );
  },
});

export default HostPage;
<|endoftext|>


<commit_before>/*

Jquery Ajax enabled Multiselect control

Written By: Alan Lai
Date:       8/25/2011

Parameters:

dataUrl:        url to a Json feed that returns objects {id = [id value], label = [label value]}
minLength:      minimum length before a search is executed
placeholder:    placeholder text for the search box
debug:          debug flag to provide more information
showOptions:    show the entire list when clicking into the text box

Callbacks:

onSelected:     event raised when a new item is selected (parameters: multiselect, id and label)
onRemoved:     event raised when a selected item is removed (parameters: multiselect, id and label)

*/

(function ($) {

    $.fn.extend({

        multiSelector: function (options) {

            var settings = $.extend({

                dataUrl: '',
                minLength: 2,
                placeholder: '',
                debug: false,
                showOptions: false,
                autoComplete: true,

                onSelected: undefined,
                onRemove: undefined

            }, options); // end of settings

            return this.each(function (index, item) {

                // get the main controls
                var $multiselect = $(this);
                $multiselect.hide();
                var $container = $("<div>").addClass("ac-container").addClass("ac-gradientbackground");
                $container.insertAfter($multiselect);

                // initialize all the necessary controls and containers
                init($multiselect, $container);
                bindEvents($multiselect, $container);

                preloadItems($multiselect, $container);

            });

            // initialize the controls
            function init($multiselect, $container) {

                // create the controls
                var $searchContainer = $("<div>").addClass("ac-searchContainer");
                var $searchBox = $("<input>").addClass("ac-searchBox").attr("placeholder", settings.placeholder);
                var $loadingIcon = $("<div>").html(" ").addClass("ac-loading").hide();
                var $selectedContainer = $("<div>").addClass("ac-selectedContainer");

                // append the controls
                $searchContainer.append($searchBox);
                $searchContainer.append($loadingIcon);
                $container.append($searchContainer);
                $container.append($selectedContainer);

                // initialize the search results box
                var $optionsBox = $("<div>").addClass("ac-optionsbox").hide();
                var $optionsList = $("<ul>").addClass("ac-optionslist").addClass("ui-menu ui-autocomplete ui-widget ui-widget-content");
                $optionsBox.append($optionsList);
                $optionsBox.insertAfter($searchBox);

                $container.append($("<div>").css("clear", "both"));

                if (settings.debug) initDebug($container);

                configureSearch($multiselect, $container);
            }

            function preloadItems($multiselect, $container) {

                var selected = $multiselect.find("option:selected");
                $.each(selected, function (index, item) {

                    var id = $(item).val();
                    var label = $(item).text();
                    onSelected($container, $multiselect, id, label);

                });

            }

            function bindEvents($multiselect, $container) {

                // detect click outside of our controls
                $('body').click(function (event) {

                    var $target = $(event.target);

                    if ($target.parents(".ac-optionsbox").length == 0 && !$target.hasClass("ac-searchBox")) {
                        $container.find(".ac-optionsbox").hide();
                    }

                });

                // capture down arrow from the textbox
                $container.find(".ac-searchBox").keydown(function (event) {

                    // get the options box next to the search box
                    var $optionBox = $(this).siblings(".ac-optionsbox");

                    // up/down and at least one item is eligible to be selected
                    if ((event.keyCode == 40 || event.keyCode == 38) && $optionBox.find("a").length > 0) {

                        var $selected = $optionBox.find(".ui-state-hover");
                        // any of them have a ui-state-hover
                        if ($selected.length > 0) {

                            // scroll up one
                            if (event.keyCode == 38) {

                                $selected.prev().addClass("ui-state-hover");
                                $selected.removeClass("ui-state-hover");

                            }

                            // scroll down one
                            if (event.keyCode == 40) {

                                $selected.next().addClass("ui-state-hover");
                                $selected.removeClass("ui-state-hover");

                            }

                        }
                        // nothing selected in the options box
                        else {
                            $optionBox.find("li").removeClass("ui-state-hover");

                            // set the first one to be highlighted
                            $optionBox.find("li:first").addClass("ui-state-hover");
                        }

                    }

                    // enter key
                    if (event.keyCode == 13) {

                        var $selected = $optionBox.find(".ui-state-hover a");
                        onSelected($container, $multiselect, $selected.data("id"), $selected.html());

                        $optionBox.hide();
                        $(this).val("");

                    }

                });

                $container.find(".ac-searchBox").keypress(function (event) { if (event.keyCode == 13) { return false; } });

            }

            function initDebug($container) {

                var $debugList = $("<ul>").addClass("ac-debug-list");

                $debugList.append($("<li>").addClass("ac-debug-item").html("Term Length:").append($("<span>").addClass("ac-debug-text")));

                var $debugContainer = $("<div>").addClass("ac-debug-container");
                $debugContainer.append($debugList);
                $container.append($debugContainer);

            }

            // =================================================
            // search events on the text box
            // =================================================
            function configureSearch($multiselect, $container) {

                var $searchBox = $container.find(".ac-searchBox");

                // use auto complete functionality
                if (settings.autoComplete) {
                    $searchBox.keyup(function (event) {

                        if (event.keyCode != 38 && event.keyCode != 40 && event.keyCode != 39 && event.keyCode != 41) {

                            var searchTerm = $searchBox.val();

                            if (settings.debug) { $container.find(".ac-debug-termLength").html('[' + searchTerm + ']' + searchTerm.length); }

                            if (searchTerm.length >= settings.minLength) {

                                onSearch(searchTerm, $multiselect, $container);

                            }
                        }

                    });
                }
                // disable the auto complete
                else {

                    var $searchButton = $("<div>").html("Search").css("margin-left", "5px");

                    $searchButton.click(function () {

                        var searchTerm = $searchBox.val();

                        onSearch(searchTerm, $multiselect, $container);

                    });

                    $searchButton.button();

                    // add an event handler for hitting enter
                    $searchBox.keyup(function (event) {

                        if (event.keyCode == 13) {

                            var searchTerm = $searchBox.val();

                            onSearch(searchTerm, $multiselect, $container);
                        }

                    });

                    $searchButton.insertAfter($searchBox);
                }

                if (settings.showOptions) {
                    // show all
                    $searchBox.click(function () {

                        var results = $multiselect.find("option:not(:selected)");
                        var available = $.map(results, function (item, index) {

                            return { id: $(item).val(), label: $(item).text() };

                        });

                        displaySearchResults(available, $container, $multiselect);

                    });
                }

            }
            // =================================================

            // event when a search is being executed
            function onSearch(searchTerm, $multiselect, $container) {

                // execute remote search
                if (settings.dataUrl != '') {
                    remoteSearch(searchTerm, $multiselect, $container);
                }
                // execute a local search
                else {
                    localSearch(searchTerm, $multiselect, $container);
                }

            }

            // execute a search against the remote datasource
            function remoteSearch(searchTerm, $multiselect, $container) {

                $.getJSON(settings.dataUrl, { searchTerm: searchTerm }, function (results) {

                    displaySearchResults(results, $container, $multiselect);

                });

            }

            // execute a search against the multiselect values
            function localSearch(searchTerm, $multiselect, $container) {

                // find the items in the multiselect
                var results = $multiselect.find("option").filter(function () {

                    var id = $(this).val().toLowerCase();
                    var txt = $(this).text().toLowerCase();

                    return (id.indexOf(searchTerm) >= 0 || txt.indexOf(searchTerm) >= 0);

                });

                var available = $.map(results, function (item, index) {

                    return { Id: $(item).val(), Label: $(item).text() };

                });

                displaySearchResults(available, $container, $multiselect);
            }

            function displaySearchResults(results, $container, $multiselect) {

                // check if the result box is visible (show if not)
                var $optionsBox = $container.find(".ac-optionsbox");
                if (!$optionsBox.is(":visible")) { $optionsBox.show(); }

                var $optionsList = $optionsBox.find(".ac-optionslist");
                $optionsList.empty();

                $.each(results, function (index, item) {

                    var link;
                    if (item.id == undefined) {
                        link = $("<a>").data("id", item.Id).html(item.Label).addClass("ac-option");
                    }
                    if (item.Id == undefined) {
                        link = $("<a>").data("id", item.id).html(item.label).addClass("ac-option");
                    }

                    link.click(function () {

                        var id = $(this).data("id");
                        var label = $(this).html();

                        onSelected($container, $multiselect, id, label);
                        $container.find(".ac-optionsbox").hide();

                    });

                    var li = $("<li>").addClass("ui-menu-item");
                    li.hover(
                    // mouse over
                        function () {
                            $(this).siblings("li.ui-menu-item").removeClass("ui-state-hover");
                            $(this).addClass("ui-state-hover");
                        },
                    // mouse out
                        function () {
                            $(this).removeClass("ui-state-hover");
                        });
                    li.append(link);

                    $optionsList.append(li);

                });

                if ($optionsList.children().length == 0) {
                    $optionsList.append($("<li>").html("No results found."));
                }

            }

            // event when an object is selected to the list
            function onSelected($container, $multiselect, id, label) {

                $container = $container.find(".ac-selectedContainer");

                // create the objects
                var $selected = $("<span>").addClass("ac-selected").data("id", id).addClass("ac-gradientbackground");
                $selected.append($("<span>").html(label).css("display", "inline-block"));
                $selected.append($("<span>").addClass("ui-icon ui-icon-circle-close").css("margin", "-3px 4px").css("display", "inline-block"));
                $selected.data("id", id);

                // check if the option exists yet
                var $selectedOption = $multiselect.find('option[value="' + id + '"]');

                if ($selectedOption.length < 1) {
                    // add the value into the multiselect control
                    $multiselect.append($("<option>").val(id).html(label).attr("selected", ""));
                }
                else {
                    $selectedOption.attr("selected", "");
                }

                var $selectedDisplayObj = $container.children().filter(function (index) { return $(this).data("id") == id; });

                // do not add the object if it already exists
                if ($selectedDisplayObj.length < 1) {
                    // add to the selected container
                    $container.append($selected);

                    // blank the search box
                    $container.parents(".ac-container").find(".ac-searchBox").val("");

                    // attach a click event
                    $selected.click(function () {

                        // remove the object from the multiselect
                        $multiselect.find('option[value="' + id + '"]').removeAttr("selected");

                        // remove from the container
                        $(this).remove();

                        if (settings.onRemoved != undefined) {
                            settings.onRemoved($multiselect, id, label);
                        }

                    });
                }

                if (settings.onSelected != undefined) {
                    settings.onSelected($multiselect, id, label);
                }

            }

        } // end of multiSelector

    }); // end of fn.extend

})(jQuery);<commit_msg>Added a z-index of 1000 to the multiSelector dowp down lsit<commit_after>/*

Jquery Ajax enabled Multiselect control

Written By: Alan Lai
Date:       8/25/2011

Parameters:

dataUrl:        url to a Json feed that returns objects {id = [id value], label = [label value]}
minLength:      minimum length before a search is executed
placeholder:    placeholder text for the search box
debug:          debug flag to provide more information
showOptions:    show the entire list when clicking into the text box

Callbacks:

onSelected:     event raised when a new item is selected (parameters: multiselect, id and label)
onRemoved:     event raised when a selected item is removed (parameters: multiselect, id and label)

*/

(function ($) {

    $.fn.extend({

        multiSelector: function (options) {

            var settings = $.extend({

                dataUrl: '',
                minLength: 2,
                placeholder: '',
                debug: false,
                showOptions: false,
                autoComplete: true,

                onSelected: undefined,
                onRemove: undefined

            }, options); // end of settings

            return this.each(function (index, item) {

                // get the main controls
                var $multiselect = $(this);
                $multiselect.hide();
                var $container = $("<div>").addClass("ac-container").addClass("ac-gradientbackground");
                $container.insertAfter($multiselect);

                // initialize all the necessary controls and containers
                init($multiselect, $container);
                bindEvents($multiselect, $container);

                preloadItems($multiselect, $container);

            });

            // initialize the controls
            function init($multiselect, $container) {

                // create the controls
                var $searchContainer = $("<div>").addClass("ac-searchContainer");
                var $searchBox = $("<input>").addClass("ac-searchBox").attr("placeholder", settings.placeholder);
                var $loadingIcon = $("<div>").html(" ").addClass("ac-loading").hide();
                var $selectedContainer = $("<div>").addClass("ac-selectedContainer");

                // append the controls
                $searchContainer.append($searchBox);
                $searchContainer.append($loadingIcon);
                $container.append($searchContainer);
                $container.append($selectedContainer);

                // initialize the search results box
                var $optionsBox = $("<div>").addClass("ac-optionsbox").hide();
                var $optionsList = $("<ul  style='z-index:1000'>").addClass("ac-optionslist").addClass("ui-menu ui-autocomplete ui-widget ui-widget-content");
                $optionsBox.append($optionsList);
                $optionsBox.insertAfter($searchBox);

                $container.append($("<div>").css("clear", "both"));

                if (settings.debug) initDebug($container);

                configureSearch($multiselect, $container);
            }

            function preloadItems($multiselect, $container) {

                var selected = $multiselect.find("option:selected");
                $.each(selected, function (index, item) {

                    var id = $(item).val();
                    var label = $(item).text();
                    onSelected($container, $multiselect, id, label);

                });

            }

            function bindEvents($multiselect, $container) {

                // detect click outside of our controls
                $('body').click(function (event) {

                    var $target = $(event.target);

                    if ($target.parents(".ac-optionsbox").length == 0 && !$target.hasClass("ac-searchBox")) {
                        $container.find(".ac-optionsbox").hide();
                    }

                });

                // capture down arrow from the textbox
                $container.find(".ac-searchBox").keydown(function (event) {

                    // get the options box next to the search box
                    var $optionBox = $(this).siblings(".ac-optionsbox");

                    // up/down and at least one item is eligible to be selected
                    if ((event.keyCode == 40 || event.keyCode == 38) && $optionBox.find("a").length > 0) {

                        var $selected = $optionBox.find(".ui-state-hover");
                        // any of them have a ui-state-hover
                        if ($selected.length > 0) {

                            // scroll up one
                            if (event.keyCode == 38) {

                                $selected.prev().addClass("ui-state-hover");
                                $selected.removeClass("ui-state-hover");

                            }

                            // scroll down one
                            if (event.keyCode == 40) {

                                $selected.next().addClass("ui-state-hover");
                                $selected.removeClass("ui-state-hover");

                            }

                        }
                        // nothing selected in the options box
                        else {
                            $optionBox.find("li").removeClass("ui-state-hover");

                            // set the first one to be highlighted
                            $optionBox.find("li:first").addClass("ui-state-hover");
                        }

                    }

                    // enter key
                    if (event.keyCode == 13) {

                        var $selected = $optionBox.find(".ui-state-hover a");
                        onSelected($container, $multiselect, $selected.data("id"), $selected.html());

                        $optionBox.hide();
                        $(this).val("");

                    }

                });

                $container.find(".ac-searchBox").keypress(function (event) { if (event.keyCode == 13) { return false; } });

            }

            function initDebug($container) {

                var $debugList = $("<ul>").addClass("ac-debug-list");

                $debugList.append($("<li>").addClass("ac-debug-item").html("Term Length:").append($("<span>").addClass("ac-debug-text")));

                var $debugContainer = $("<div>").addClass("ac-debug-container");
                $debugContainer.append($debugList);
                $container.append($debugContainer);

            }

            // =================================================
            // search events on the text box
            // =================================================
            function configureSearch($multiselect, $container) {

                var $searchBox = $container.find(".ac-searchBox");

                // use auto complete functionality
                if (settings.autoComplete) {
                    $searchBox.keyup(function (event) {

                        if (event.keyCode != 38 && event.keyCode != 40 && event.keyCode != 39 && event.keyCode != 41) {

                            var searchTerm = $searchBox.val();

                            if (settings.debug) { $container.find(".ac-debug-termLength").html('[' + searchTerm + ']' + searchTerm.length); }

                            if (searchTerm.length >= settings.minLength) {

                                onSearch(searchTerm, $multiselect, $container);

                            }
                        }

                    });
                }
                // disable the auto complete
                else {

                    var $searchButton = $("<div>").html("Search").css("margin-left", "5px");

                    $searchButton.click(function () {

                        var searchTerm = $searchBox.val();

                        onSearch(searchTerm, $multiselect, $container);

                    });

                    $searchButton.button();

                    // add an event handler for hitting enter
                    $searchBox.keyup(function (event) {

                        if (event.keyCode == 13) {

                            var searchTerm = $searchBox.val();

                            onSearch(searchTerm, $multiselect, $container);
                        }

                    });

                    $searchButton.insertAfter($searchBox);
                }

                if (settings.showOptions) {
                    // show all
                    $searchBox.click(function () {

                        var results = $multiselect.find("option:not(:selected)");
                        var available = $.map(results, function (item, index) {

                            return { id: $(item).val(), label: $(item).text() };

                        });

                        displaySearchResults(available, $container, $multiselect);

                    });
                }

            }
            // =================================================

            // event when a search is being executed
            function onSearch(searchTerm, $multiselect, $container) {

                // execute remote search
                if (settings.dataUrl != '') {
                    remoteSearch(searchTerm, $multiselect, $container);
                }
                // execute a local search
                else {
                    localSearch(searchTerm, $multiselect, $container);
                }

            }

            // execute a search against the remote datasource
            function remoteSearch(searchTerm, $multiselect, $container) {

                $.getJSON(settings.dataUrl, { searchTerm: searchTerm }, function (results) {

                    displaySearchResults(results, $container, $multiselect);

                });

            }

            // execute a search against the multiselect values
            function localSearch(searchTerm, $multiselect, $container) {

                // find the items in the multiselect
                var results = $multiselect.find("option").filter(function () {

                    var id = $(this).val().toLowerCase();
                    var txt = $(this).text().toLowerCase();

                    return (id.indexOf(searchTerm) >= 0 || txt.indexOf(searchTerm) >= 0);

                });

                var available = $.map(results, function (item, index) {

                    return { Id: $(item).val(), Label: $(item).text() };

                });

                displaySearchResults(available, $container, $multiselect);
            }

            function displaySearchResults(results, $container, $multiselect) {

                // check if the result box is visible (show if not)
                var $optionsBox = $container.find(".ac-optionsbox");
                if (!$optionsBox.is(":visible")) { $optionsBox.show(); }

                var $optionsList = $optionsBox.find(".ac-optionslist");
                $optionsList.empty();

                $.each(results, function (index, item) {

                    var link;
                    if (item.id == undefined) {
                        link = $("<a>").data("id", item.Id).html(item.Label).addClass("ac-option");
                    }
                    if (item.Id == undefined) {
                        link = $("<a>").data("id", item.id).html(item.label).addClass("ac-option");
                    }

                    link.click(function () {

                        var id = $(this).data("id");
                        var label = $(this).html();

                        onSelected($container, $multiselect, id, label);
                        $container.find(".ac-optionsbox").hide();

                    });

                    var li = $("<li>").addClass("ui-menu-item");
                    li.hover(
                    // mouse over
                        function () {
                            $(this).siblings("li.ui-menu-item").removeClass("ui-state-hover");
                            $(this).addClass("ui-state-hover");
                        },
                    // mouse out
                        function () {
                            $(this).removeClass("ui-state-hover");
                        });
                    li.append(link);

                    $optionsList.append(li);

                });

                if ($optionsList.children().length == 0) {
                    $optionsList.append($("<li>").html("No results found."));
                }

            }

            // event when an object is selected to the list
            function onSelected($container, $multiselect, id, label) {

                $container = $container.find(".ac-selectedContainer");

                // create the objects
                var $selected = $("<span>").addClass("ac-selected").data("id", id).addClass("ac-gradientbackground");
                $selected.append($("<span>").html(label).css("display", "inline-block"));
                $selected.append($("<span>").addClass("ui-icon ui-icon-circle-close").css("margin", "-3px 4px").css("display", "inline-block"));
                $selected.data("id", id);

                // check if the option exists yet
                var $selectedOption = $multiselect.find('option[value="' + id + '"]');

                if ($selectedOption.length < 1) {
                    // add the value into the multiselect control
                    $multiselect.append($("<option>").val(id).html(label).attr("selected", ""));
                }
                else {
                    $selectedOption.attr("selected", "");
                }

                var $selectedDisplayObj = $container.children().filter(function (index) { return $(this).data("id") == id; });

                // do not add the object if it already exists
                if ($selectedDisplayObj.length < 1) {
                    // add to the selected container
                    $container.append($selected);

                    // blank the search box
                    $container.parents(".ac-container").find(".ac-searchBox").val("");

                    // attach a click event
                    $selected.click(function () {

                        // remove the object from the multiselect
                        $multiselect.find('option[value="' + id + '"]').removeAttr("selected");

                        // remove from the container
                        $(this).remove();

                        if (settings.onRemoved != undefined) {
                            settings.onRemoved($multiselect, id, label);
                        }

                    });
                }

                if (settings.onSelected != undefined) {
                    settings.onSelected($multiselect, id, label);
                }

            }

        } // end of multiSelector

    }); // end of fn.extend

})(jQuery);<|endoftext|>


<commit_before>const buildMouseEvent = (type, target, {which, ctrlKey, relatedTarget} = {}) => {
  const event = new MouseEvent(type, {bubbles: true, cancelable: true})
  if (which != null) {
    Object.defineProperty(event, 'which', {
      get () {
        return which
      }
    })
  }

  if (ctrlKey != null) {
    Object.defineProperty(event, 'ctrlKey', {
      get () {
        return ctrlKey
      }
    })
  }

  if (relatedTarget != null) {
    Object.defineProperty(event, 'relatedTarget', {
      get () {
        return relatedTarget
      }
    })
  }

  Object.defineProperty(event, 'target', {
    get () {
      return target
    }
  })

  Object.defineProperty(event, 'srcObject', {
    get () {
      return target
    }
  })

  spyOn(event, 'preventDefault')
  return event
}

module.exports.triggerMouseEvent = (type, target, {which, ctrlKey} = {}) => {
  const event = buildMouseEvent(type, target, {which, ctrlKey})
  target.dispatchEvent(event)
  return event
}

module.exports.triggerClickEvent = (target, options) => {
  const events = {
    mousedown: buildMouseEvent('mousedown', target, options),
    mouseup: buildMouseEvent('mouseup', target, options),
    click: buildMouseEvent('click', target, options)
  }

  target.dispatchEvent(events.mousedown)
  target.dispatchEvent(events.mouseup)
  target.dispatchEvent(events.click)

  return events
}

module.exports.buildDragEvents = (dragged, dropTarget) => {
  const dataTransfer = {
    data: {},
    setData (key, value) {
      this.data[key] = `${value}` // Drag events stringify data values
    },
    getData (key) {
      return this.data[key]
    }
  }

  Object.defineProperty(
    dataTransfer,
    'items', {
      get () {
        return Object.keys(dataTransfer.data).map(key => ({type: key}))
      }
    }
  )

  const dragStartEvent = buildMouseEvent('dragstart', dragged)
  Object.defineProperty(dragStartEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })

  const dropEvent = buildMouseEvent('drop', dropTarget)
  Object.defineProperty(dropEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })

  return [dragStartEvent, dropEvent]
}

module.exports.buildDragEnterLeaveEvents = (enterRelatedTarget, leaveRelatedTarget) => {
  const dataTransfer = {
    data: {},
    setData (key, value) {
      this.data[key] = `${value}` // Drag events stringify data values
    },
    getData (key) {
      return this.data[key]
    }
  }

  Object.defineProperty(
    dataTransfer,
    'items', {
      get () {
        return Object.keys(dataTransfer.data).map(key => ({type: key}))
      }
    }
  )

  const dragEnterEvent = buildMouseEvent('dragenter', null, {relatedTarget: enterRelatedTarget})
  Object.defineProperty(dragEnterEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })

  const dragLeaveEvent = buildMouseEvent('dragleave', null, {relatedTarget: leaveRelatedTarget})
  Object.defineProperty(dragLeaveEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })

  return [dragEnterEvent, dragLeaveEvent]
}

module.exports.buildWheelEvent = delta => new WheelEvent('mousewheel', {wheelDeltaY: delta})

module.exports.buildWheelPlusShiftEvent = delta => new WheelEvent('mousewheel', {wheelDeltaY: delta, shiftKey: true})
<commit_msg>Fix new specs<commit_after>const buildMouseEvent = (type, target, {which, ctrlKey, relatedTarget} = {}) => {
  const event = new MouseEvent(type, {bubbles: true, cancelable: true})
  if (which != null) {
    Object.defineProperty(event, 'which', {
      get () {
        return which
      }
    })
  }

  if (ctrlKey != null) {
    Object.defineProperty(event, 'ctrlKey', {
      get () {
        return ctrlKey
      }
    })
  }

  if (relatedTarget != null) {
    Object.defineProperty(event, 'relatedTarget', {
      get () {
        return relatedTarget
      }
    })
  }

  Object.defineProperty(event, 'target', {
    get () {
      return target
    }
  })

  Object.defineProperty(event, 'srcObject', {
    get () {
      return target
    }
  })

  spyOn(event, 'preventDefault')
  return event
}

module.exports.triggerMouseEvent = (type, target, {which, ctrlKey} = {}) => {
  const event = buildMouseEvent(type, target, {which, ctrlKey})
  target.dispatchEvent(event)
  return event
}

module.exports.triggerClickEvent = (target, options) => {
  const events = {
    mousedown: buildMouseEvent('mousedown', target, options),
    mouseup: buildMouseEvent('mouseup', target, options),
    click: buildMouseEvent('click', target, options)
  }

  target.dispatchEvent(events.mousedown)
  target.dispatchEvent(events.mouseup)
  target.dispatchEvent(events.click)

  return events
}

module.exports.buildDragEvents = (dragged, dropTarget) => {
  const dataTransfer = {
    data: {},
    setData (key, value) {
      this.data[key] = `${value}` // Drag events stringify data values
    },
    getData (key) {
      return this.data[key]
    }
  }

  Object.defineProperty(
    dataTransfer,
    'items', {
      get () {
        return Object.keys(dataTransfer.data).map(key => ({type: key}))
      }
    }
  )

  const dragStartEvent = buildMouseEvent('dragstart', dragged)
  Object.defineProperty(dragStartEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })

  const dropEvent = buildMouseEvent('drop', dropTarget)
  Object.defineProperty(dropEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })

  return [dragStartEvent, dropEvent]
}

module.exports.buildDragEnterLeaveEvents = (enterRelatedTarget, leaveRelatedTarget) => {
  const dataTransfer = {
    data: {},
    setData (key, value) {
      this.data[key] = `${value}` // Drag events stringify data values
    },
    getData (key) {
      return this.data[key]
    }
  }

  Object.defineProperty(
    dataTransfer,
    'items', {
      get () {
        return Object.keys(dataTransfer.data).map(key => ({type: key}))
      }
    }
  )

  const dragEnterEvent = buildMouseEvent('dragenter', null, {relatedTarget: enterRelatedTarget})
  Object.defineProperty(dragEnterEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })
  dragEnterEvent.dataTransfer.setData('atom-tab-event', 'true')

  const dragLeaveEvent = buildMouseEvent('dragleave', null, {relatedTarget: leaveRelatedTarget})
  Object.defineProperty(dragLeaveEvent, 'dataTransfer', {
    get () {
      return dataTransfer
    }
  })
  dragLeaveEvent.dataTransfer.setData('atom-tab-event', 'true')

  return [dragEnterEvent, dragLeaveEvent]
}

module.exports.buildWheelEvent = delta => new WheelEvent('mousewheel', {wheelDeltaY: delta})

module.exports.buildWheelPlusShiftEvent = delta => new WheelEvent('mousewheel', {wheelDeltaY: delta, shiftKey: true})
<|endoftext|>


<commit_before>import { WKT, GeoJSON } from 'ol/format';
import {transform, transformExtent, get as getProj} from 'ol/proj';
import {Polygon, LineString, GeometryType, Point} from 'ol/geom';
import Feature from 'ol/Feature';
import { Vector } from 'ol/source';
import * as loadingstrategy from 'ol/loadingstrategy';

function rainbow(numOfSteps, step, opacity) {
    // based on http://stackoverflow.com/a/7419630
    // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distiguishable vibrant markers in Google Maps and other apps.
    // Adam Cole, 2011-Sept-14
    // HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
    var r, g, b;
    var h = step / (numOfSteps * 1.00000001);
    var i = ~~(h * 4);
    var f = h * 4 - i;
    var q = 1 - f;
    switch (i % 4) {
        case 2:
            r = f, g = 1, b = 0;
            break;
        case 0:
            r = 0, g = f, b = 1;
            break;
        case 3:
            r = 1, g = q, b = 0;
            break;
        case 1:
            r = 0, g = 1, b = q;
            break;
    }
    var c = "rgba(" + ~~(r * 235) + "," + ~~(g * 235) + "," + ~~(b * 235) + ", " + opacity + ")";
    return (c);
}

function registerCategoryForStatistics(feature_object, options, feature, category_map, category_id) {
    if (feature_object[options.category_field]) {
        if (typeof category_map[feature_object[options.category_field]] === 'undefined') {
            category_map[feature_object[options.category_field]] = {
                id: category_id,
                name: feature_object[options.category_field]
            };
            category_id++;
        }
        feature.category_id = category_map[feature_object[options.category_field]].id;
    }
}

function loadFeatures(objects, src, options, occupied_xy, category_map, category_id) {
    var features = [];
    var i = 0.0;
    var format = new WKT();
    for (var key in objects) {
        i++;
        if (objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#lat"] && objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#long"] && objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#lat"] != "" && objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#long"] != "") {
            var x = parseFloat(objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#long"]);
            var y = parseFloat(objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#lat"]);
            if (!isNaN(x) && !isNaN(y)) {
                var coord = transform([x, y], 'EPSG:4326', 'EPSG:3857');
                if (typeof occupied_xy[coord] !== 'undefined') continue;
                objects[key].geometry = new Point(coord);
                var feature = new Feature(objects[key]);
                registerCategoryForStatistics(objects[key], options, feature, category_map, category_id);
                occupied_xy[coord] = true;
                features.push(feature);
            }
        }
        if (objects[key]["http://www.opengis.net/ont/geosparql#asWKT"]) {
            var g_feature = format.readFeature(objects[key]['http://www.opengis.net/ont/geosparql#asWKT'].toUpperCase());
            objects[key].geometry = g_feature.getGeometry();
            objects[key].geometry.transform('EPSG:4326', options.projection);
            delete objects[key]['http://www.opengis.net/ont/geosparql#asWKT'];
            var coord = objects[key].geometry.getCoordinates();

            if (typeof occupied_xy[coord] !== 'undefined') continue;
            var feature = new Feature(objects[key]);
            registerCategoryForStatistics(objects[key], options, feature, category_map, category_id);
            occupied_xy[coord] = true;
            features.push(feature);
        }
    }
    for (var categ in category_map) {
        category_map[categ].color = rainbow(category_id, category_map[categ].id, 0.7);
    }
    src.legend_categories = category_map;
    for (var i = 0; i < features.length; i++) {
        if (features[i].category_id) {
            features[i].color = rainbow(category_id, features[i].category_id, 0.7);
        }
    }
    return features;
}

function extendAttributes(options, objects) {
    if (typeof options.extend_with_attribs != 'undefined') {
        for (var attr_i in options.extend_with_attribs) {
            for (var i in objects) {
                if (typeof objects[i][options.extend_with_attribs[attr_i]] == 'undefined') {
                    objects[i][options.extend_with_attribs[attr_i]] = '';
                }
            }
        }
    }
}

export default function (options) {
    var category_map = {};
    var category_id = 0;
    var occupied_xy = {};
    var src = new Vector({
        format: new GeoJSON(),
        loader: function (extent, resolution, projection) {
            this.set('loaded', false);
            if (typeof this.options.clear_on_move !== 'undefined' && this.options.clear_on_move) this.clear();
            if (typeof options.hsproxy == 'undefined') options.hsproxy = false;
            if (typeof options.geom_attribute == 'undefined') options.geom_attribute = 'bif:st_point(xsd:decimal(?lon), xsd:decimal(?lat))';
            if (this.options.url == '') return;
            var p = this.options.url;
            var first_pair = [extent[0], extent[1]];
            var second_pair = [extent[2], extent[3]];
            first_pair = transform(first_pair, 'EPSG:3857', 'EPSG:4326');
            second_pair = transform(second_pair, 'EPSG:3857', 'EPSG:4326');
            var extent = [first_pair[0], first_pair[1], second_pair[0], second_pair[1]];
            var s_extent = 'FILTER(bif:st_intersects(bif:st_geomfromtext("BOX(' + extent[0] + ' ' + extent[1] + ', ' + extent[2] + ' ' + extent[3] + ')"), ' + options.geom_attribute + ')).';
            p = p.replace("<extent>", s_extent);
            if (options.hsproxy)
                p = "/cgi-bin/hsproxy.cgi?toEncoding=utf-8&url=" + encodeURIComponent(p);
            if (console && typeof src.get('geoname') != 'undefined') console.log('Get ', src.get('geoname'));
            if (console) console.log(s_extent);
            this.loadCounter += 1;
            this.loadTotal += 1;
            $.ajax({
                url: p,
                context: this
            })
                .done(function (response) {
                    if (console)
                        console.log('Finish ', this.get('geoname'), response.results.bindings.length);
                    src.loadCounter -= 1;
                    if (this.options.updates_url) {
                        var updates_query = this.options.updates_url;
                        updates_query = updates_query.replace("<extent>", s_extent);
                        src.loadCounter += 1;
                        src.loadTotal += 1;
                        $.ajax({
                            url: updates_query,
                            context: this
                        })
                            .done(function (updates_response) {
                                if (console && typeof this.get('geoname') != 'undefined')
                                    console.log('Finish updates ', this.get('geoname'), response.results.bindings.length, updates_response.results.bindings.length);
                                var objects = {};
                                for (var i = 0; i < response.results.bindings.length; i++) {
                                    var b = response.results.bindings[i];
                                    if (typeof objects[b.o.value] === 'undefined') {
                                        objects[b.o.value] = {
                                            'poi_id': b.o.value
                                        };
                                    }
                                    objects[b.o.value][b.p.value] = b.s.value;
                                }
                                for (var i = 0; i < updates_response.results.bindings.length; i++) {
                                    var b = updates_response.results.bindings[i];
                                    var attribute_name = b.attr.value;
                                    //Because photos can be more than one
                                    if (typeof objects[b.o.value][attribute_name] != 'undefined' && attribute_name == 'http://xmlns.com/foaf/0.1/depiction') {
                                        for (var try_i = 1; try_i < 20; try_i++) {
                                            if (typeof objects[b.o.value][attribute_name + try_i] == 'undefined') {
                                                attribute_name = attribute_name + try_i;
                                                break;
                                            }
                                        }
                                    }
                                    objects[b.o.value][attribute_name] = b.value.value;
                                }
                                if (typeof options.category != 'undefined') {
                                    for (var i in objects) {
                                        objects[i]['http://www.sdi4apps.eu/poi/#mainCategory'] = options.category;
                                    }
                                }
                                extendAttributes(options, objects);
                                if (console)
                                    console.log('Add features', objects);
                                this.addFeatures(loadFeatures(objects, this, options, occupied_xy, category_map, category_id));
                                src.loadCounter -= 1;
                                this.set('last_feature_count', Object.keys(objects).length);
                                if (src.loadCounter == 0) {
                                    this.set('loaded', true);
                                    this.dispatchEvent('imageloadend');
                                }
                            })
                    } else {
                        var objects = {};
                        for (var i = 0; i < response.results.bindings.length; i++) {
                            var b = response.results.bindings[i];
                            if (typeof objects[b.o.value] === 'undefined') {
                                objects[b.o.value] = {
                                    'poi_id': b.o.value
                                };
                            }
                            objects[b.o.value][b.p.value] = b.s.value;
                        }
                        if (typeof options.category != 'undefined') {
                            for (var i in objects) {
                                objects[i]['http://www.sdi4apps.eu/poi/#mainCategory'] = options.category;
                            }
                        }
                        extendAttributes(options, objects);
                        this.addFeatures(loadFeatures(objects, this, options, occupied_xy, category_map, category_id));
                        this.styleAble = true;
                        this.hasPoint = true;
                        src.loadCounter -= 1;
                        this.set('last_feature_count', Object.keys(objects).length);
                        if (src.loadCounter == 0) {
                            this.set('loaded', true);
                            this.dispatchEvent('imageloadend');
                        }
                    }
                })
        },
        strategy: options.strategy || function (extent, resolution) {
            var tmp = [extent[0], extent[1], extent[2], extent[3]];
            if (extent[2] - extent[0] > 65735) {
                tmp[0] = (extent[2] + extent[0]) / 2.0 - 65735 / 2.0;
                tmp[2] = (extent[2] + extent[0]) / 2.0 + 65735 / 2.0;
                tmp[1] = (extent[3] + extent[1]) / 2.0 - 35000 / 2.0;
                tmp[3] = (extent[3] + extent[1]) / 2.0 + 35000 / 2.0;
            }
            return [tmp];
        },
        projection: options.projection
    });
    src.loadCounter = 0;
    src.loadTotal = 0;
    src.options = options;
    src.legend_categories = category_map;
    return src;
};
<commit_msg>SparqlJson update This is a minimal bugfix of issue #307. Needs further rework though.<commit_after>import { WKT, GeoJSON } from 'ol/format';
import { transform, transformExtent, get as getProj } from 'ol/proj';
import { Polygon, LineString, GeometryType, Point } from 'ol/geom';
import Feature from 'ol/Feature';
import { Vector } from 'ol/source';
import * as loadingstrategy from 'ol/loadingstrategy';

function rainbow(numOfSteps, step, opacity) {
    // based on http://stackoverflow.com/a/7419630
    // This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distiguishable vibrant markers in Google Maps and other apps.
    // Adam Cole, 2011-Sept-14
    // HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
    var r, g, b;
    var h = step / (numOfSteps * 1.00000001);
    var i = ~~(h * 4);
    var f = h * 4 - i;
    var q = 1 - f;
    switch (i % 4) {
        case 2:
            r = f, g = 1, b = 0;
            break;
        case 0:
            r = 0, g = f, b = 1;
            break;
        case 3:
            r = 1, g = q, b = 0;
            break;
        case 1:
            r = 0, g = 1, b = q;
            break;
    }
    var c = "rgba(" + ~~(r * 235) + "," + ~~(g * 235) + "," + ~~(b * 235) + ", " + opacity + ")";
    return (c);
}

function registerCategoryForStatistics(feature_object, options, feature, category_map, category_id) {
    if (feature_object[options.category_field]) {
        if (typeof category_map[feature_object[options.category_field]] === 'undefined') {
            category_map[feature_object[options.category_field]] = {
                id: category_id,
                name: feature_object[options.category_field]
            };
            category_id++;
        }
        feature.category_id = category_map[feature_object[options.category_field]].id;
    }
}

function loadFeatures(objects, src, options, occupied_xy, category_map, category_id) {
    var features = [];
    var format = new WKT();
    for (var key in objects) {
        if (objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#lat"] && objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#long"] && objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#lat"] != "" && objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#long"] != "") {
            var x = parseFloat(objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#long"]);
            var y = parseFloat(objects[key]["http://www.w3.org/2003/01/geo/wgs84_pos#lat"]);
            if (!isNaN(x) && !isNaN(y)) {
                var coord = transform([x, y], 'EPSG:4326', 'EPSG:3857');
                if (typeof occupied_xy[coord] !== 'undefined') continue;
                objects[key].geometry = new Point(coord);
                var feature = new Feature(objects[key]);
                registerCategoryForStatistics(objects[key], options, feature, category_map, category_id);
                occupied_xy[coord] = true;
                features.push(feature);
            }
        }
        if (objects[key]["http://www.opengis.net/ont/geosparql#asWKT"]) {
            console.log("foo");
            var g_feature = format.readFeature(objects[key]['http://www.opengis.net/ont/geosparql#asWKT'].toUpperCase());
            objects[key].geometry = g_feature.getGeometry();
            objects[key].geometry.transform('EPSG:4326', options.projection);
            delete objects[key]['http://www.opengis.net/ont/geosparql#asWKT'];
            var coord = objects[key].geometry.getCoordinates();

            if (typeof occupied_xy[coord] !== 'undefined') continue;
            var feature = new Feature(objects[key]);
            registerCategoryForStatistics(objects[key], options, feature, category_map, category_id);
            occupied_xy[coord] = true;
            features.push(feature);
        }
    }
    for (var categ in category_map) {
        category_map[categ].color = rainbow(category_id, category_map[categ].id, 0.7);
    }
    src.legend_categories = category_map;
    for (var i = 0; i < features.length; i++) {
        if (features[i].category_id) {
            features[i].color = rainbow(category_id, features[i].category_id, 0.7);
        }
    }
    console.log(features);
    return features;
}

function extendAttributes(options, objects) {
    if (typeof options.extend_with_attribs != 'undefined') {
        for (var attr_i in options.extend_with_attribs) {
            for (var i in objects) {
                if (typeof objects[i][options.extend_with_attribs[attr_i]] == 'undefined') {
                    objects[i][options.extend_with_attribs[attr_i]] = '';
                }
            }
        }
    }
}

export default function (options) {
    var category_map = {};
    var category_id = 0;
    var occupied_xy = {};
    var src = new Vector({
        format: new GeoJSON(),
        loader: function (extent, resolution, projection) {
            this.set('loaded', false);
            if (typeof this.options.clear_on_move !== 'undefined' && this.options.clear_on_move) this.clear();
            if (typeof options.hsproxy == 'undefined') options.hsproxy = false;
            if (typeof options.geom_attribute == 'undefined') options.geom_attribute = 'bif:st_point(xsd:decimal(?lon), xsd:decimal(?lat))';
            if (this.options.url == '') return;
            var p = this.options.url;
            var first_pair = [extent[0], extent[1]];
            var second_pair = [extent[2], extent[3]];
            first_pair = transform(first_pair, 'EPSG:3857', 'EPSG:4326');
            second_pair = transform(second_pair, 'EPSG:3857', 'EPSG:4326');
            var extent = [first_pair[0], first_pair[1], second_pair[0], second_pair[1]];
            var s_extent = encodeURIComponent('FILTER(geof:sfIntersects("POLYGON((' +
                extent[0] + ' ' + extent[1] + ', ' +
                extent[0] + ' ' + extent[3] + ', ' +
                extent[2] + ' ' + extent[3] + ', ' +
                extent[2] + ' ' + extent[1] + ', ' +
                extent[0] + ' ' + extent[1] +
                '))"^^geo:wktLiteral, ' + options.geom_attribute + ')).');
            let tmp = p.split("&query=");
            p = tmp[0] + "&query=" +
                encodeURIComponent("PREFIX geo: <http://www.opengis.net/ont/geosparql#>\n" +
                "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>\n") + tmp[1];
            p = p.replace("<extent>", s_extent);
            if (options.hsproxy)
                p = "/cgi-bin/hsproxy.cgi?toEncoding=utf-8&url=" + encodeURIComponent(p);
            if (console && typeof src.get('geoname') != 'undefined') console.log('Get ', src.get('geoname'));
            this.loadCounter += 1;
            this.loadTotal += 1;
            $.ajax({
                url: p,
                context: this
            })
                .done(function (response) {
                    if (console)
                        console.log('Finish ', this.get('geoname'), response.results.bindings.length);
                    src.loadCounter -= 1;
                    if (this.options.updates_url) {
                        var updates_query = this.options.updates_url;
                        let tmp = updates_query.split("&query=");
                        updates_query = tmp[0] + "&query=" +
                            encodeURIComponent("PREFIX geo: <http://www.opengis.net/ont/geosparql#>\n" +
                            "PREFIX geof: <http://www.opengis.net/def/function/geosparql/>\n") + tmp[1];
                        updates_query = updates_query.replace("<extent>", s_extent);
                        src.loadCounter += 1;
                        src.loadTotal += 1;
                        $.ajax({
                            url: updates_query,
                            context: this
                        })
                            .done(function (updates_response) {
                                if (console && typeof this.get('geoname') != 'undefined')
                                    console.log('Finish updates ', this.get('geoname'), response.results.bindings.length, updates_response.results.bindings.length);
                                let objects = {};
                                for (const item of response.results.bindings) {
                                    if (typeof objects[item.o.value] === 'undefined') {
                                        objects[item.o.value] = {
                                            'poi_id': item.o.value
                                        };
                                    }
                                    objects[item.o.value][item.p.value] = item.s.value;
                                }
                                for (const item of updates_response.results.bindings) {
                                    let attribute_name = item.attr.value;
                                    //Because photos can be more than one
                                    if (typeof objects[item.o.value][attribute_name] != 'undefined' && attribute_name == 'http://xmlns.com/foaf/0.1/depiction') {
                                        for (let try_i = 1; try_i < 20; try_i++) {
                                            if (typeof objects[item.o.value][attribute_name + try_i] == 'undefined') {
                                                attribute_name = attribute_name + try_i;
                                                break;
                                            }
                                        }
                                    }
                                    objects[item.o.value][attribute_name] = item.value.value;
                                }
                                if (typeof options.category != 'undefined') {
                                    for (let i in objects) {
                                        objects[i]['http://www.sdi4apps.eu/poi/#mainCategory'] = options.category;
                                    }
                                }
                                extendAttributes(options, objects);
                                if (console) {
                                    console.log('Add features', objects);
                                    console.log(this);
                                  }
                                this.addFeatures(loadFeatures(objects, this, options, occupied_xy, category_map, category_id));
                                src.loadCounter -= 1;
                                this.set('last_feature_count', Object.keys(objects).length);
                                if (src.loadCounter == 0) {
                                    this.set('loaded', true);
                                    this.dispatchEvent('imageloadend');
                                }
                            })
                    } else {
                        var objects = {};
                        for (var i = 0; i < response.results.bindings.length; i++) {
                            var b = response.results.bindings[i];
                            if (typeof objects[b.o.value] === 'undefined') {
                                objects[b.o.value] = {
                                    'poi_id': b.o.value
                                };
                            }
                            objects[b.o.value][b.p.value] = b.s.value;
                        }
                        if (typeof options.category != 'undefined') {
                            for (var i in objects) {
                                objects[i]['http://www.sdi4apps.eu/poi/#mainCategory'] = options.category;
                            }
                        }
                        extendAttributes(options, objects);
                        this.addFeatures(loadFeatures(objects, this, options, occupied_xy, category_map, category_id));
                        this.styleAble = true;
                        this.hasPoint = true;
                        src.loadCounter -= 1;
                        this.set('last_feature_count', Object.keys(objects).length);
                        if (src.loadCounter == 0) {
                            this.set('loaded', true);
                            this.dispatchEvent('imageloadend');
                        }
                    }
                })
        },
        strategy: options.strategy || function (extent, resolution) {
            var tmp = [extent[0], extent[1], extent[2], extent[3]];
            if (extent[2] - extent[0] > 65735) {
                tmp[0] = (extent[2] + extent[0]) / 2.0 - 65735 / 2.0;
                tmp[2] = (extent[2] + extent[0]) / 2.0 + 65735 / 2.0;
                tmp[1] = (extent[3] + extent[1]) / 2.0 - 35000 / 2.0;
                tmp[3] = (extent[3] + extent[1]) / 2.0 + 35000 / 2.0;
            }
            return [tmp];
        },
        projection: options.projection
    });
    src.loadCounter = 0;
    src.loadTotal = 0;
    src.options = options;
    src.legend_categories = category_map;
    console.log("src");
    console.log(src);
    return src;
};
<|endoftext|>


<commit_before>'use strict';

function each(list) {
    var cursor = list.head;
    var result = '';

    if (cursor === null) {
        return result;
    }

    if (cursor === list.tail) {
        return translate(list.head.data);
    }

    while (cursor !== null) {
        result += translate(cursor.data);
        cursor = cursor.next;
    }

    return result;
}

function eachDelim(list, delimeter) {
    var cursor = list.head;
    var result = '';

    if (cursor === null) {
        return result;
    }

    if (cursor === list.tail) {
        return translate(list.head.data);
    }

    while (true) {
        result += translate(cursor.data);
        cursor = cursor.next;
        if (cursor === null) {
            break;
        }
        result += delimeter;
    }

    return result;
}

function translateAtRule(node) {
    var result = '@' + node.name;

    if (node.expression !== null) {
        result += ' ' + translate(node.expression);
    }

    if (node.block) {
        result += translate(node.block);
    } else {
        result += ';';
    }

    return result;
}

function translateBlock(list) {
    var cursor = list.head;
    var result = '';

    if (cursor === null) {
        return result;
    }

    if (cursor === list.tail) {
        return translate(list.head.data);
    }

    while (cursor !== null) {
        result += translate(cursor.data);
        if (cursor.next && cursor.data.type === 'Declaration') {
            result += ';';
        }
        cursor = cursor.next;
    }

    return result;
}

function translate(node) {
    switch (node.type) {
        case 'StyleSheet':
            return each(node.children);

        case 'Atrule':
            return translateAtRule(node);

        case 'Rule':
            return translate(node.selector) + translate(node.block);

        case 'SelectorList':
            return eachDelim(node.children, ',');

        case 'Selector':
            return each(node.children);

        case 'Block':
            return '{' + translateBlock(node.children) + '}';

        case 'DeclarationList':
            return translateBlock(node.children);

        case 'Declaration':
            return node.important
                ? node.property + ':' + translate(node.value) + '!important'
                : node.property + ':' + translate(node.value);

        case 'Value':
            return each(node.children);

        case 'Nth':
            var result = translate(node.nth);
            if (node.selector !== null) {
                result += ' of ' + translate(node.selector);
            }
            return result;

        case 'AttributeSelector':
            var result = translate(node.name);
            var flagsPrefix = ' ';

            if (node.operator !== null) {
                result += node.operator;

                if (node.value !== null) {
                    result += translate(node.value);

                    // space between string and flags is not required
                    if (node.value.type === 'String') {
                        flagsPrefix = '';
                    }
                }
            }

            if (node.flags !== null) {
                result += flagsPrefix + node.flags;
            }

            return '[' + result + ']';

        case 'Function':
            return node.name + '(' + each(node.children) + ')';

        case 'Parentheses':
            return '(' + each(node.children) + ')';

        case 'Brackets':
            return '[' + each(node.children) + ']';

        case 'AtruleExpression':
            return each(node.children);

        case 'MediaQueryList':
            return eachDelim(node.children, ',');

        case 'MediaQuery':
            return each(node.children);

        case 'MediaFeature':
            return node.value !== null
                ? '(' + node.name + ':' + translate(node.value) + ')'
                : '(' + node.name + ')';

        case 'Url':
            return 'url(' + translate(node.value) + ')';

        case 'Combinator':
            return node.name;

        case 'TypeSelector':
            return node.name;

        case 'Identifier':
            return node.name;

        case 'PseudoClassSelector':
            return node.children !== null
                ? ':' + node.name + '(' + each(node.children) + ')'
                : ':' + node.name;

        case 'PseudoElementSelector':
            return node.children !== null
                ? '::' + node.name + '(' + each(node.children) + ')'
                : '::' + node.name;

        case 'ClassSelector':
            return '.' + node.name;

        case 'IdSelector':
            return '#' + node.name;

        case 'UnicodeRange':
            return node.value;

        case 'HexColor':
            return '#' + node.value;

        case 'Dimension':
            return node.value + node.unit;

        case 'AnPlusB':
            var result = '';
            var a = node.a !== null && node.a !== undefined;
            var b = node.b !== null && node.b !== undefined;

            if (a) {
                result += node.a === '+1' || node.a === '1' ? 'n' :
                          node.a === '-1' ? '-n' :
                          node.a + 'n';
            }

            if (a && b) {
                if (String(node.b).charAt(0) !== '-' &&
                    String(node.b).charAt(0) !== '+') {
                    result += '+';
                }
            }

            if (b) {
                result += node.b;
            }

            return result;

        case 'Number':
            return node.value;

        case 'String':
            return node.value;

        case 'Operator':
            return node.value;

        case 'Ratio':
            return node.left + '/' + node.right;

        case 'Raw':
            return node.value;

        case 'Percentage':
            return node.value + '%';

        case 'WhiteSpace':
            return node.value;

        case 'Comment':
            return '/*' + node.value + '*/';

        default:
            throw new Error('Unknown node type: ' + node.type);
    }
}

module.exports = translate;
<commit_msg>prepare translate for extensibility<commit_after>'use strict';

var SEMICOLON = 59; // ';'.charCodeAt()
var RIGHTCURLYBRACKET = 125; // '}'.charCodeAt();

var Generator = function() {};
Generator.prototype = {
    generate: function(node) {
        if (this.type.hasOwnProperty(node.type)) {
            return this.type[node.type].call(this, node);
        } else {
            throw new Error('Unknown node type: ' + node.type);
        }
    },

    each: function(list) {
        var cursor = list.head;
        var result = '';

        if (cursor === null) {
            return result;
        }

        if (cursor === list.tail) {
            return this.generate(list.head.data);
        }

        while (cursor !== null) {
            result += this.generate(cursor.data);
            cursor = cursor.next;
        }

        return result;
    },
    eachDelim: function(list, delimeter) {
        var cursor = list.head;
        var result = '';

        if (cursor === null) {
            return result;
        }

        if (cursor === list.tail) {
            return this.generate(list.head.data);
        }

        while (cursor !== null) {
            if (result.length) {
                result += delimeter;
            }
            result += this.generate(cursor.data);
            cursor = cursor.next;
        }

        return result;
    },
    generateBlock: function(list) {
        var cursor = list.head;
        var result = '';

        if (cursor === null) {
            return result;
        }

        if (cursor === list.tail) {
            return this.generate(list.head.data);
        }

        while (cursor !== null) {
            if (result.length > 0) {
                var code = result.charCodeAt(result.length - 1);
                if (code !== RIGHTCURLYBRACKET &&
                    code !== SEMICOLON) {
                    result += ';';
                }
            }

            result += this.generate(cursor.data, cursor.next !== null);
            cursor = cursor.next;
        }

        return result;
    },

    type: {
        StyleSheet: function(node) {
            return this.each(node.children);
        },
        Atrule: function(node) {
            var result = '@' + node.name;

            if (node.expression !== null) {
                result += ' ' + this.generate(node.expression);
            }

            if (node.block) {
                result += this.generate(node.block);
            } else {
                result += ';';
            }

            return result;
        },
        AtruleExpression: function(node) {
            return this.each(node.children);
        },
        MediaQueryList: function(node) {
            return this.eachDelim(node.children, ',');
        },
        MediaQuery: function(node) {
            return this.each(node.children);
        },
        MediaFeature: function(node) {
            return node.value !== null
                ? '(' + node.name + ':' + this.generate(node.value) + ')'
                : '(' + node.name + ')';
        },
        Rule: function(node) {
            return this.generate(node.selector) + this.generate(node.block);
        },
        SelectorList: function(node) {
            return this.eachDelim(node.children, ',');
        },
        Selector: function(node) {
            return this.each(node.children);
        },
        Combinator: function(node) {
            return node.name;
        },
        TypeSelector: function(node) {
            return node.name;
        },
        ClassSelector: function(node) {
            return '.' + node.name;
        },
        IdSelector: function(node) {
            return '#' + node.name;
        },
        AttributeSelector: function(node) {
            var result = this.generate(node.name);
            var flagsPrefix = ' ';

            if (node.operator !== null) {
                result += node.operator;

                if (node.value !== null) {
                    result += this.generate(node.value);

                    // space between string and flags is not required
                    if (node.value.type === 'String') {
                        flagsPrefix = '';
                    }
                }
            }

            if (node.flags !== null) {
                result += flagsPrefix + node.flags;
            }

            return '[' + result + ']';
        },
        PseudoClassSelector: function(node) {
            return node.children !== null
                ? ':' + node.name + '(' + this.each(node.children) + ')'
                : ':' + node.name;
        },
        PseudoElementSelector: function(node) {
            return node.children !== null
                ? '::' + node.name + '(' + this.each(node.children) + ')'
                : '::' + node.name;
        },
        Nth: function(node) {
            var result = this.generate(node.nth);
            if (node.selector !== null) {
                result += ' of ' + this.generate(node.selector);
            }
            return result;
        },
        AnPlusB: function(node) {
            var result = '';
            var a = node.a !== null && node.a !== undefined;
            var b = node.b !== null && node.b !== undefined;

            if (a) {
                result += node.a === '+1' || node.a === '1' ? 'n' :
                          node.a === '-1' ? '-n' :
                          node.a + 'n';
            }

            if (a && b) {
                if (String(node.b).charAt(0) !== '-' &&
                    String(node.b).charAt(0) !== '+') {
                    result += '+';
                }
            }

            if (b) {
                result += node.b;
            }

            return result;
        },
        Block: function(node) {
            return '{' + this.generateBlock(node.children) + '}';
        },
        DeclarationList: function(node) {
            return this.generateBlock(node.children);
        },
        Declaration: function(node) {
            return node.important
                ? node.property + ':' + this.generate(node.value) + '!important'
                : node.property + ':' + this.generate(node.value);
        },
        Value: function(node) {
            return this.each(node.children);
        },
        Function: function(node) {
            return node.name + '(' + this.each(node.children) + ')';
        },
        Parentheses: function(node) {
            return '(' + this.each(node.children) + ')';
        },
        Brackets: function(node) {
            return '[' + this.each(node.children) + ']';
        },
        Url: function(node) {
            return 'url(' + this.generate(node.value) + ')';
        },
        Identifier: function(node) {
            return node.name;
        },
        UnicodeRange: function(node) {
            return node.value;
        },
        HexColor: function(node) {
            return '#' + node.value;
        },
        Dimension: function(node) {
            return node.value + node.unit;
        },
        Number: function(node) {
            return node.value;
        },
        String: function(node) {
            return node.value;
        },
        Operator: function(node) {
            return node.value;
        },
        Ratio: function(node) {
            return node.left + '/' + node.right;
        },
        Percentage: function(node) {
            return node.value + '%';
        },
        Raw: function(node) {
            return node.value;
        },
        WhiteSpace: function(node) {
            return node.value;
        },
        Comment: function(node) {
            return '/*' + node.value + '*/';
        }
    }
};

var generator = new Generator();
module.exports = generator.generate.bind(generator);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';

class PostsNew extends Component {
  renderField(field) {
    return (

        {field.label}
        <input
          className="form-control"
          type="text"
          {...field.input}
        />

    );
  }

  renderPostField(field) {
    return(

        {field.label}
        <textarea
          className="form-control"
          type="textarea"
          {...field.input}
        />

    );
  }

  render() {
    return (
      <form>
        <Field
          label="Title"
          name="title"
          component={this.renderField}
        />
        <Field
          label="Categories"
          name="categories"
          component={this.renderField}
        />
        <Field
          label="Post Content"
          name="content"
          component={this.renderPostField}
        />
      </form>
    );
  }
}

function validate(values) {
  const errors = {};

  // Validate the inputs from 'values'
  if (!values.title) {
    errors.title = "Enter a title!";
  }
  if (!values.categories) {
    errors.title = "Enter some !";
  }
  if (!values.content) {
    errors.title = "Enter a title!";
  }

  // if errors is empty, the form is fine to submit
  // if errors has any properties, redux form assumes form is invalid
  return errors;
}

export default reduxForm({
  validate,
  form: 'PostsNewForm'
})(PostsNew);
<commit_msg>Handle form submission and conditionally show error messages<commit_after>import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';

class PostsNew extends Component {
  renderField(field) {
    const { meta: { touched, error } } = field;
    const className = `form-group ${touched && error ? 'has-danger' : ''}`;

    return (

        {field.label}
        <input
          className="form-control"
          type="text"
          {...field.input}
          />

          {touched ? error : ''}

    );
  }

  renderPostField(field) {
    const { meta: { touched, error } } = field;
    const className = `form-group ${touched && error ? 'has-danger' : ''}`;

    return(

        {field.label}
        <textarea
          className="form-control"
          type="textarea"
          {...field.input}
          />
        {touched ? error : ''}

    );
  }

  onSubmit(values) {
    console.log(values);
  }

  render() {
    const { handleSubmit } = this.props;

    return (
      <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
        <Field
          label="Title"
          name="title"
          component={this.renderField}
        />
        <Field
          label="Categories"
          name="categories"
          component={this.renderField}
        />
        <Field
          label="Post Content"
          name="content"
          component={this.renderPostField}
        />
        <button type="submit" className="btn btn-primary">Submit</button>
      </form>
    );
  }
}

function validate(values) {
  const errors = {};

  // Validate the inputs from 'values'
  if (!values.title) {
    errors.title = "Enter a title!";
  }
  if (!values.categories) {
    errors.categories = "Enter some categories!";
  }
  if (!values.content) {
    errors.content = "Enter some content!";
  }

  // if errors is empty, the form is fine to submit
  // if errors has any properties, redux form assumes form is invalid
  return errors;
}

export default reduxForm({
  validate,
  form: 'PostsNewForm'
})(PostsNew);
<|endoftext|>