<commit_before>(function () {

    // Main module
    var app = angular.module('odalic-app');

    // graphvis directive
    var currentFolder = $.getPathForRelativePath('');
    app.directive('graphvis', function () {
        return {
            restrict: 'E',
            templateUrl: currentFolder + 'graphvis.html',
            scope: {
                bind: '='
            },
            link: function (scope, iElement, iAtttrs) {

                // Public interface via 'bind'
                // *******************************
                var pif = {
                    /** An event handler when an edge is clicked on.
                     *  The function has to accept 2 arguments (column1, column2).
                     *  Presumably for modal opening.
                     */
                    edgeClick: null,

                    /** Array of columns names.
                     *  Must be in correct order, i.e. $scope['inputFile']['columns'] is suitable.
                     */
                    vertices: null,

                    /** The structure holding the whole result.
                     *  Yes, this is a tight coupling, but at this point it's really not worth it to do something about it.
                     */
                    result: null,

                    /** The structure holding locks for each 2 columns.
                     *  The same applies about the tight coupling as above.
                     */
                    lockobj: null,

                    /** Signalling a model change to graphvis. */
                    modelChanged: function (column1, column2) {},

                    /** Forcing an update from outside, presumably on a modal close. */
                    update: function () {}
                };

                // Copy the interface into 'bind'
                if (!scope.bind) {
                    scope.bind = {};
                }
                objhelp.objNRCopyNew(pif, scope.bind);

                // Private
                // *******************************
                // Load the necessary modules
                var toLoad = ['graphcore.js', 'node.js', 'link.js', 'label.js', 'edgecreator.js', 'lock.js'];
                toLoad.forEach(function (item) {
                    $.getScriptSync(currentFolder + item, function () {
                        /* Purposefully empty. */
                    });
                });

                // Create a root <svg> element
                var svg = d3.select(iElement.get(0).childNodes[2])
                    .append('svg')
                    .attr('width', 1200)
                    .attr('height', 550);

                // Create a marker (arrow)
                (function () {
                    var defs = svg.append('defs');
                    defs
                        .append('marker')
                        .attrs({
                            'id': 'line-arrow-end',
                            'viewBox': '0 0 10 10',
                            'refX': 49,
                            'refY': 5,
                            'markerUnits': 'strokeWidth',
                            'orient': 'auto',
                            'markerWidth': 4,
                            'markerHeight': 4,
                            'xoverflow': 'visible'
                        })
                        .append('path')
                        .attr('d', 'M 0 0 L 10 5 L 0 10 z');
                    defs
                        .append('marker')
                        .attrs({
                            'id': 'line-arrow-start',
                            'viewBox': '0 0 10 10',
                            'refX': -41,
                            'refY': 5,
                            'markerUnits': 'strokeWidth',
                            'orient': 'auto',
                            'markerWidth': 4,
                            'markerHeight': 4,
                            'xoverflow': 'visible'
                        })
                        .append('path')
                        .attr('d', 'M -2 5 L 8 0 L 8 10 z');
                })();

                // Create a graph
                var g = new graph(svg, {
                    decay: {
                        velocity: 0.05,
                        alpha: 0.02
                    },
                    collision: {
                        radius: 75,
                        strength: 0.1
                    },
                    centering: {
                        strength: 0.1
                    },
                    linksDistance: 330,
                    manyBody: {
                        strength: 0
                    }
                });

                // General graph state, properties and functions
                var applyOnColIdcs = function (node1, node2, f) {
                    var column1 = g.vertices.indexOf(node1.id);
                    var column2 = g.vertices.indexOf(node2.id);
                    if (column1 !== column2) {
                        f(column1, column2);
                    }
                };

                var gprops = (function () {
                    var _state = 0;
                    return {
                        states: {
                            NodeDragging: 0,
                            LinkCreation: 1,
                            ResetLayout: 2
                        },
                        get state() {
                            return _state;
                        },
                        set state(value) {
                            if (_state != value) {
                                _state = value;

                                // Call each vertex and edge and inform it about the state update
                                var arrs = [g.vertices.arr, g.edges.arr];
                                arrs.forEach(function (arr) {
                                    arr.forEach(function (item) {
                                        var fn = 'stateEnter';
                                        if (fn in item) {
                                            item[fn]();
                                        }
                                    });
                                });
                            }
                        },
                        link: {
                            // Locks
                            setLock: function (node1, node2, locked) {
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    scope.bind.lockobj[column1][column2] = !locked;
                                });

                                // The export buttons do not get updated for some reason
                                timed.strongDigest(scope);
                            },
                            getLock:  function (node1, node2) {
                                var result = null;
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    result = !scope.bind.lockobj[column1][column2];
                                });
                                return result;
                            },

                            // Creation and editting of the labels
                            create: function (node1, node2) {
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    scope.bind.edgeClick(column1, column2);
                                });
                            },
                            settings: function (node1, node2) {
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    scope.bind.edgeClick(column1, column2);
                                });
                            },
                            hoveredNode: null
                        },
                        graph: {
                            canvas: {
                                get width() {
                                    return svg.attr('width');
                                },
                                get height() {
                                    return svg.attr('height');
                                }
                            }
                        }
                    };
                })();

                // Set state; reset layout button
                (function () {
                    // Set state
                    scope.setDraggingDis = function () {
                        return (gprops.state === gprops.states.NodeDragging)
                    };
                    scope.setDragging = function () {
                        gprops.state = gprops.states.NodeDragging;
                    };
                    scope.setLinkCreationDis = function () {
                        return (gprops.state === gprops.states.LinkCreation)
                    };
                    scope.setLinkCreation = function () {
                        gprops.state = gprops.states.LinkCreation;
                    };

                    // Reset layout button
                    scope.resetLayoutDis = function () {
                        return (gprops.state !== gprops.states.NodeDragging);
                    };
                    scope.resetLayout = function () {
                        if (!scope.resetLayoutDis()) {
                            gprops.state = gprops.states.ResetLayout;
                            gprops.state = gprops.states.NodeDragging;
                        }
                    };
                })();

                // Prepare
                var node = nodeWrapper(gprops);
                var link = linkWrapper(gprops);

                // Generate vertices
                scope.bind.vertices.forEach(function (item) {
                    g.vertices.addItem(new node(item));
                });

                // Edges model reflection; generate edges
                (function () {
                    var modelChanged = function (column1, column2) {
                        var vertex1 = g.vertices.arr[column1].id;
                        var vertex2 = g.vertices.arr[column2].id;

                        var selection = scope.bind.result['columnRelationAnnotations'][column1][column2]['chosen'];

                        var e = g.edges.find(vertex1, vertex2);
                        var labels = [];

                        // Construct predicate label for a given KB and a candidate
                        var handleCandidate = function (kb, candidate) {
                            var prefix = candidate['prefixed'];
                            if (prefix) {
                                // Display the prefix on edge, if defined
                                labels.push(prefix);
                            } else {
                                // The old way - display "label (KB)"
                                var concept = candidate['label'];
                                if (!concept) {
                                    var resource = candidate['resource'];
                                    try {
                                        concept = text.uri(resource).page;
                                    } catch (e) {
                                        concept = text.dotted(resource, 20);
                                    }
                                }
                                labels.push((new String()).concat(concept, '(', kb, ')'));
                            }
                        };

                        // Retrieve selected predicate labels
                        objhelp.objForEach(selection, function (kb, scArr) {
                            if (kb === 'other') {
                                if (scArr && scArr[0]['entity']['resource']) {
                                    handleCandidate(kb, scArr[0]['entity']);
                                }
                                return;
                            }

                            scArr.forEach(function (candidate) {
                                handleCandidate(kb, candidate['entity']);
                            });
                        });

                        // Set the label
                        if (labels.length > 0) {
                            if (e === null) {
                                e = new link(column1, column2);
                                var _e = g.edges.addItem(e);
                                e = _e ? _e : e;
                                g.forceUpdate();
                            }
                            e.setLabel(labels.join(', '), vertex1, vertex2);
                        }
                        // Remove the whole edge as there are no selected relations
                        else {
                            if (e !== null) {
                                g.edges.removeItem(vertex1, vertex2);
                            }
                        }
                    };

                    // Set the event handler for model changes
                    scope.bind.modelChanged = function (column1, column2) {
                        modelChanged(column1, column2);
                    };

                    // Generate first edges the similar way
                    objhelp.objForEach(scope.bind.result['columnRelationAnnotations'], function (column1, cl1) {
                        objhelp.objForEach(cl1, function (column2, cl2) {
                            modelChanged(parseInt(column1), parseInt(column2));
                        });
                    });
                })();

                // Forced update
                scope.bind.update = function () {
                    g.forceUpdate();
                };

                // Stop simulation on the directive destruction
                iElement.on('$destroy', function() {
                    g.destroy();
                });
            }
        }
    });

})();<commit_msg>(Debugging messages)<commit_after>(function () {

    // Main module
    var app = angular.module('odalic-app');

    // graphvis directive
    var currentFolder = $.getPathForRelativePath('');
    app.directive('graphvis', function () {
        return {
            restrict: 'E',
            templateUrl: currentFolder + 'graphvis.html',
            scope: {
                bind: '='
            },
            link: function (scope, iElement, iAtttrs) {

                console.log('created');

                // Public interface via 'bind'
                // *******************************
                var pif = {
                    /** An event handler when an edge is clicked on.
                     *  The function has to accept 2 arguments (column1, column2).
                     *  Presumably for modal opening.
                     */
                    edgeClick: null,

                    /** Array of columns names.
                     *  Must be in correct order, i.e. $scope['inputFile']['columns'] is suitable.
                     */
                    vertices: null,

                    /** The structure holding the whole result.
                     *  Yes, this is a tight coupling, but at this point it's really not worth it to do something about it.
                     */
                    result: null,

                    /** The structure holding locks for each 2 columns.
                     *  The same applies about the tight coupling as above.
                     */
                    lockobj: null,

                    /** Signalling a model change to graphvis. */
                    modelChanged: function (column1, column2) {},

                    /** Forcing an update from outside, presumably on a modal close. */
                    update: function () {}
                };

                // Copy the interface into 'bind'
                if (!scope.bind) {
                    scope.bind = {};
                }
                objhelp.objNRCopyNew(pif, scope.bind);

                // Private
                // *******************************
                // Load the necessary modules
                var toLoad = ['graphcore.js', 'node.js', 'link.js', 'label.js', 'edgecreator.js', 'lock.js'];
                toLoad.forEach(function (item) {
                    $.getScriptSync(currentFolder + item, function () {
                        /* Purposefully empty. */
                    });
                });

                // Create a root <svg> element
                var svg = d3.select(iElement.get(0).childNodes[2])
                    .append('svg')
                    .attr('width', 1200)
                    .attr('height', 550);

                // Create a marker (arrow)
                (function () {
                    var defs = svg.append('defs');
                    defs
                        .append('marker')
                        .attrs({
                            'id': 'line-arrow-end',
                            'viewBox': '0 0 10 10',
                            'refX': 49,
                            'refY': 5,
                            'markerUnits': 'strokeWidth',
                            'orient': 'auto',
                            'markerWidth': 4,
                            'markerHeight': 4,
                            'xoverflow': 'visible'
                        })
                        .append('path')
                        .attr('d', 'M 0 0 L 10 5 L 0 10 z');
                    defs
                        .append('marker')
                        .attrs({
                            'id': 'line-arrow-start',
                            'viewBox': '0 0 10 10',
                            'refX': -41,
                            'refY': 5,
                            'markerUnits': 'strokeWidth',
                            'orient': 'auto',
                            'markerWidth': 4,
                            'markerHeight': 4,
                            'xoverflow': 'visible'
                        })
                        .append('path')
                        .attr('d', 'M -2 5 L 8 0 L 8 10 z');
                })();

                // Create a graph
                var g = new graph(svg, {
                    decay: {
                        velocity: 0.05,
                        alpha: 0.02
                    },
                    collision: {
                        radius: 75,
                        strength: 0.1
                    },
                    centering: {
                        strength: 0.1
                    },
                    linksDistance: 330,
                    manyBody: {
                        strength: 0
                    }
                });

                // General graph state, properties and functions
                var applyOnColIdcs = function (node1, node2, f) {
                    var column1 = g.vertices.indexOf(node1.id);
                    var column2 = g.vertices.indexOf(node2.id);
                    if (column1 !== column2) {
                        f(column1, column2);
                    }
                };

                var gprops = (function () {
                    var _state = 0;
                    return {
                        states: {
                            NodeDragging: 0,
                            LinkCreation: 1,
                            ResetLayout: 2
                        },
                        get state() {
                            return _state;
                        },
                        set state(value) {
                            if (_state != value) {
                                _state = value;

                                // Call each vertex and edge and inform it about the state update
                                var arrs = [g.vertices.arr, g.edges.arr];
                                arrs.forEach(function (arr) {
                                    arr.forEach(function (item) {
                                        var fn = 'stateEnter';
                                        if (fn in item) {
                                            item[fn]();
                                        }
                                    });
                                });
                            }
                        },
                        link: {
                            // Locks
                            setLock: function (node1, node2, locked) {
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    scope.bind.lockobj[column1][column2] = !locked;
                                });

                                // The export buttons do not get updated for some reason
                                timed.strongDigest(scope);
                            },
                            getLock:  function (node1, node2) {
                                var result = null;
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    result = !scope.bind.lockobj[column1][column2];
                                });
                                return result;
                            },

                            // Creation and editting of the labels
                            create: function (node1, node2) {
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    scope.bind.edgeClick(column1, column2);
                                });
                            },
                            settings: function (node1, node2) {
                                applyOnColIdcs(node1, node2, function (column1, column2) {
                                    scope.bind.edgeClick(column1, column2);
                                });
                            },
                            hoveredNode: null
                        },
                        graph: {
                            canvas: {
                                get width() {
                                    return svg.attr('width');
                                },
                                get height() {
                                    return svg.attr('height');
                                }
                            }
                        }
                    };
                })();

                // Set state; reset layout button
                (function () {
                    // Set state
                    scope.setDraggingDis = function () {
                        return (gprops.state === gprops.states.NodeDragging)
                    };
                    scope.setDragging = function () {
                        gprops.state = gprops.states.NodeDragging;
                    };
                    scope.setLinkCreationDis = function () {
                        return (gprops.state === gprops.states.LinkCreation)
                    };
                    scope.setLinkCreation = function () {
                        gprops.state = gprops.states.LinkCreation;
                    };

                    // Reset layout button
                    scope.resetLayoutDis = function () {
                        return (gprops.state !== gprops.states.NodeDragging);
                    };
                    scope.resetLayout = function () {
                        if (!scope.resetLayoutDis()) {
                            gprops.state = gprops.states.ResetLayout;
                            gprops.state = gprops.states.NodeDragging;
                        }
                    };
                })();

                // Prepare
                var node = nodeWrapper(gprops);
                var link = linkWrapper(gprops);

                // Generate vertices
                scope.bind.vertices.forEach(function (item) {
                    g.vertices.addItem(new node(item));
                });

                // Edges model reflection; generate edges
                (function () {
                    var modelChanged = function (column1, column2) {
                        var vertex1 = g.vertices.arr[column1].id;
                        var vertex2 = g.vertices.arr[column2].id;

                        var selection = scope.bind.result['columnRelationAnnotations'][column1][column2]['chosen'];

                        var e = g.edges.find(vertex1, vertex2);
                        var labels = [];

                        // Construct predicate label for a given KB and a candidate
                        var handleCandidate = function (kb, candidate) {
                            var prefix = candidate['prefixed'];
                            if (prefix) {
                                // Display the prefix on edge, if defined
                                labels.push(prefix);
                            } else {
                                // The old way - display "label (KB)"
                                var concept = candidate['label'];
                                if (!concept) {
                                    var resource = candidate['resource'];
                                    try {
                                        concept = text.uri(resource).page;
                                    } catch (e) {
                                        concept = text.dotted(resource, 20);
                                    }
                                }
                                labels.push((new String()).concat(concept, '(', kb, ')'));
                            }
                        };

                        // Retrieve selected predicate labels
                        objhelp.objForEach(selection, function (kb, scArr) {
                            if (kb === 'other') {
                                if (scArr && scArr[0]['entity']['resource']) {
                                    handleCandidate(kb, scArr[0]['entity']);
                                }
                                return;
                            }

                            scArr.forEach(function (candidate) {
                                handleCandidate(kb, candidate['entity']);
                            });
                        });

                        // Set the label
                        if (labels.length > 0) {
                            if (e === null) {
                                e = new link(column1, column2);
                                var _e = g.edges.addItem(e);
                                e = _e ? _e : e;
                                g.forceUpdate();
                            }
                            e.setLabel(labels.join(', '), vertex1, vertex2);
                        }
                        // Remove the whole edge as there are no selected relations
                        else {
                            if (e !== null) {
                                g.edges.removeItem(vertex1, vertex2);
                            }
                        }
                    };

                    // Set the event handler for model changes
                    scope.bind.modelChanged = function (column1, column2) {
                        modelChanged(column1, column2);
                    };

                    // Generate first edges the similar way
                    objhelp.objForEach(scope.bind.result['columnRelationAnnotations'], function (column1, cl1) {
                        objhelp.objForEach(cl1, function (column2, cl2) {
                            modelChanged(parseInt(column1), parseInt(column2));
                        });
                    });
                })();

                // Forced update
                scope.bind.update = function () {
                    g.forceUpdate();
                };

                // Stop simulation on the directive destruction
                iElement.on('$destroy', function() {
                    console.log('destroyed');
                    g.destroy();
                });
            }
        }
    });

})();<|endoftext|>


<commit_before>import pathToRegexp from 'path-to-regexp'

/**
  @typedef  {Object} Route
  @property {String} path         url expr
  @property {Array}  methods      http methods
  @property {Array}  childs       the module's sub Route (ModuleRoute only)
 */

/**
 * math routes
 * @param  {Array} routers  array of routers to match
 * @param  {String} path    the path of url
 * @param  {String} method  the method of http request
 * @return {Array}          the matched route [route] or [route, params]
 */

export function matchRouter (routers, path, method) {
  let len = routers.length
  let step = 0
  let params = {}
  let route
  let isModule
  while (step < len) {
    route = routers[step++]
    isModule = !!route.childs
    if (matchRoute(route.path, params, path, {end: !isModule, sensitive: true})) {
      if (isModule) {
        return [route]
      }
      if (route.methods.indexOf(method) !== -1) {
        return [route, params]
      }
    }
  }
}

let regexpCache = []

export function matchRoute (path, params, pathname, opts) {
  let keys, regexp
  let key = `${opts.end}-${opts.sensitive}-${path}`// unique
  const hit = regexpCache[key]
  if (hit) {
    keys = hit.keys
    regexp = hit.regexp
  } else {
    keys = []
    regexp = pathToRegexp(path, keys, opts)
    regexpCache[key] = {keys, regexp}
  }
  const m = pathname.match(regexp)
  if (!m) {
    return false
  }
  if (params) {
    for (let i = 1, len = m.length; i < len; ++i) {
      const key = keys[i - 1]
      if (key) {
        const val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i]
        params[key.name] = val
      }
    }
  }
  return true
}
<commit_msg>fixed test case<commit_after>import pathToRegexp from 'path-to-regexp'

/**
  @typedef  {Object} Route
  @property {String} path         url expr
  @property {Array}  methods      http methods
  @property {Array}  childs       the module's sub Route (ModuleRoute only)
 */

/**
 * math routes
 * @param  {Array} routers  array of routers to match
 * @param  {String} path    the path of url
 * @param  {String} method  the method of http request
 * @return {Array}          the matched route [route] or [route, params]
 */

export function matchRouter (routers, path, method) {
  let len = routers.length
  let step = 0
  let params = {}
  let route
  let isModule
  while (step < len) {
    route = routers[step++]
    isModule = !!route.childs
    if (matchRoute(route.path, params, path, {end: !isModule, sensitive: true})) {
      if (isModule) {
        return [route]
      }
      if (route.methods.indexOf(method) !== -1) {
        return [route, params]
      }
    }
  }
}

let regexpCache = []

export function matchRoute (path, params, pathname, opts = {}) {
  let keys, regexp
  let key = `${opts.end}-${opts.sensitive}-${path}`// unique
  const hit = regexpCache[key]
  if (hit) {
    keys = hit.keys
    regexp = hit.regexp
  } else {
    keys = []
    regexp = pathToRegexp(path, keys, opts)
    regexpCache[key] = {keys, regexp}
  }
  const m = pathname.match(regexp)
  if (!m) {
    return false
  }
  if (params) {
    for (let i = 1, len = m.length; i < len; ++i) {
      const key = keys[i - 1]
      if (key) {
        const val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i]
        params[key.name] = val
      }
    }
  }
  return true
}
<|endoftext|>


<commit_before>/* global angular */
'use strict'; // jshint ignore:line

angular.module('lumx.select', [])
    .controller('LxSelectController', ['$scope', '$compile', '$filter', '$interpolate', '$sce',
                                       function($scope, $compile, $filter, $interpolate, $sce)
    {
        var self = this;

        // Link methods
        this.init = function(element, attrs)
        {
            $scope.multiple = angular.isDefined(attrs.multiple);
            $scope.tree = angular.isDefined(attrs.tree);
        };

        this.registerTransclude = function(transclude)
        {
            $scope.selectedTransclude = transclude;
        };

        this.getScope = function()
        {
            return $scope;
        };

        // Selection management
        function select(choice)
        {
            if ($scope.multiple)
            {
                if ($scope.selected.indexOf(choice) === -1)
                {
                    $scope.selected.push(choice);
                }
            }
            else
            {
                $scope.selected = [choice];
            }
        }

        function unselect(element, event)
        {
            if (!$scope.allowClear && !$scope.multiple)
            {
                return;
            }

            if (angular.isDefined(event) && !$scope.multiple)
            {
                event.stopPropagation();
            }

            var index = $scope.selected.indexOf(element);
            if (index !== -1)
            {
                $scope.selected.splice(index, 1);
            }
        }

        function toggle(choice, event)
        {
            if (angular.isDefined(event) && $scope.multiple)
            {
                event.stopPropagation();
            }

            if ($scope.multiple && isSelected(choice))
            {
                unselect(choice);
            }
            else
            {
                select(choice);
            }
        }

        // Getters
        function isSelected(choice)
        {
            return $scope.selected.indexOf(choice) !== -1;
        }

        function hasNoResults()
        {
            return angular.isUndefined($scope.choices) || $filter('filter')($scope.choices, $scope.data.filter).length === 0;
        }

        function filterNeeded()
        {
            return angular.isDefined($scope.minLength) && $scope.data.filter.length < $scope.minLength;
        }

        function isHelperVisible()
        {
            return $scope.loading !== 'true' && (filterNeeded() || (hasNoResults() && !filterNeeded()));
        }

        function isChoicesVisible()
        {
            return $scope.loading !== 'true' && !hasNoResults() && !filterNeeded();
        }

        /**
         * Return the array of selected elements. Always return an array (ie. returns an empty array in case
         * selected list is undefined in the scope).
         */
        function getSelectedElements()
        {
            return angular.isDefined($scope.selected) ? $scope.selected : [];
        }

        function getSelectedTemplate()
        {
            return $sce.trustAsHtml($scope.selectedTemplate);
        }

        // Watchers
        $scope.$watch('selected', function(newValue, oldValue)
        {
            if (angular.isDefined(newValue) && angular.isDefined($scope.selectedTransclude))
            {
                var newScope = $scope.$new();
                $scope.selectedTemplate = '';

                angular.forEach(newValue, function(selectedElement)
                {
                    newScope.$selected = selectedElement;

                    $scope.selectedTransclude(newScope, function(clone)
                    {
                        var div = angular.element('<div/>'),
                            element = $compile(clone)(newScope),
                            content = $interpolate(clone.html())(newScope);

                        element.html(content);

                        div.append(element);

                        if ($scope.multiple)
                        {
                            div.find('span').addClass('lx-select__tag');
                        }

                        $scope.selectedTemplate += div.html();
                    });
                });

                // Exec function callback if set
                $scope.change({ newValue: newValue, oldValue: oldValue });
            }
        }, true);

        $scope.$watch('data.filter', function(newValue, oldValue)
        {
            if(angular.isUndefined($scope.minLength) || (newValue && $scope.minLength <= newValue.length))
            {
                $scope.filter({ newValue: newValue, oldValue: oldValue });
            }
        });

        // Public API
        $scope.select = select;
        $scope.unselect = unselect;
        $scope.toggle = toggle;
        $scope.isChoicesVisible = isChoicesVisible;
        $scope.isHelperVisible = isHelperVisible;
        $scope.isSelected = isSelected;
        $scope.filterNeeded = filterNeeded;
        $scope.getSelectedElements = getSelectedElements;
        $scope.getSelectedTemplate = getSelectedTemplate;
        $scope.hasNoResults = hasNoResults;
    }])
    .directive('lxSelect', function()
    {
        return {
            restrict: 'E',
            controller: 'LxSelectController',
            scope: {
                selected: '=',
                placeholder: '@',
                choices: '=',
                loading: '@',
                minLength: '@',
                allowClear: '@',
                change: '&', // Parameters: newValue, oldValue
                filter: '&' // Parameters: newValue, oldValue
            },
            templateUrl: 'lumx.select.html',
            transclude: true,
            replace: true,
            link: function(scope, element, attrs, ctrl)
            {
                ctrl.init(element, attrs);
                scope.data = {
                    filter: ''
                };
            }
        };
    })
    .directive('lxSelectSelected', function()
    {
        return {
            restrict: 'E',
            require: '^lxSelect',
            templateUrl: 'lumx.select_selected.html',
            transclude: true,
            link: function(scope, element, attrs, ctrl, transclude)
            {
                ctrl.registerTransclude(transclude);
                scope.data = ctrl.getScope();
            }
        };
    })
    .directive('lxSelectChoices', function()
    {
        return {
            restrict: 'E',
            require: '^lxSelect',
            templateUrl: 'lumx.select_choices.html',
            transclude: true,
            link: function(scope, element, attrs, ctrl)
            {
                scope.data = ctrl.getScope();
            }
        };
    });
<commit_msg>fix select: null pointer on filter if none selected<commit_after>/* global angular */
'use strict'; // jshint ignore:line

angular.module('lumx.select', [])
    .controller('LxSelectController', ['$scope', '$compile', '$filter', '$interpolate', '$sce',
                                       function($scope, $compile, $filter, $interpolate, $sce)
    {
        var self = this;

        // Link methods
        this.init = function(element, attrs)
        {
            $scope.multiple = angular.isDefined(attrs.multiple);
            $scope.tree = angular.isDefined(attrs.tree);
        };

        this.registerTransclude = function(transclude)
        {
            $scope.selectedTransclude = transclude;
        };

        this.getScope = function()
        {
            return $scope;
        };

        // Selection management
        function select(choice)
        {
            if ($scope.multiple)
            {
                if ($scope.selected.indexOf(choice) === -1)
                {
                    $scope.selected.push(choice);
                }
            }
            else
            {
                $scope.selected = [choice];
            }
        }

        function unselect(element, event)
        {
            if (!$scope.allowClear && !$scope.multiple)
            {
                return;
            }

            if (angular.isDefined(event) && !$scope.multiple)
            {
                event.stopPropagation();
            }

            var index = $scope.selected.indexOf(element);
            if (index !== -1)
            {
                $scope.selected.splice(index, 1);
            }
        }

        function toggle(choice, event)
        {
            if (angular.isDefined(event) && $scope.multiple)
            {
                event.stopPropagation();
            }

            if ($scope.multiple && isSelected(choice))
            {
                unselect(choice);
            }
            else
            {
                select(choice);
            }
        }

        // Getters
        function isSelected(choice)
        {
            return angular.isDefined($scope.selected) && $scope.selected.indexOf(choice) !== -1;
        }

        function hasNoResults()
        {
            return angular.isUndefined($scope.choices) || $filter('filter')($scope.choices, $scope.data.filter).length === 0;
        }

        function filterNeeded()
        {
            return angular.isDefined($scope.minLength) && $scope.data.filter.length < $scope.minLength;
        }

        function isHelperVisible()
        {
            return $scope.loading !== 'true' && (filterNeeded() || (hasNoResults() && !filterNeeded()));
        }

        function isChoicesVisible()
        {
            return $scope.loading !== 'true' && !hasNoResults() && !filterNeeded();
        }

        /**
         * Return the array of selected elements. Always return an array (ie. returns an empty array in case
         * selected list is undefined in the scope).
         */
        function getSelectedElements()
        {
            return angular.isDefined($scope.selected) ? $scope.selected : [];
        }

        function getSelectedTemplate()
        {
            return $sce.trustAsHtml($scope.selectedTemplate);
        }

        // Watchers
        $scope.$watch('selected', function(newValue, oldValue)
        {
            if (angular.isDefined(newValue) && angular.isDefined($scope.selectedTransclude))
            {
                var newScope = $scope.$new();
                $scope.selectedTemplate = '';

                angular.forEach(newValue, function(selectedElement)
                {
                    newScope.$selected = selectedElement;

                    $scope.selectedTransclude(newScope, function(clone)
                    {
                        var div = angular.element('<div/>'),
                            element = $compile(clone)(newScope),
                            content = $interpolate(clone.html())(newScope);

                        element.html(content);

                        div.append(element);

                        if ($scope.multiple)
                        {
                            div.find('span').addClass('lx-select__tag');
                        }

                        $scope.selectedTemplate += div.html();
                    });
                });

                // Exec function callback if set
                $scope.change({ newValue: newValue, oldValue: oldValue });
            }
        }, true);

        $scope.$watch('data.filter', function(newValue, oldValue)
        {
            if(angular.isUndefined($scope.minLength) || (newValue && $scope.minLength <= newValue.length))
            {
                $scope.filter({ newValue: newValue, oldValue: oldValue });
            }
        });

        // Public API
        $scope.select = select;
        $scope.unselect = unselect;
        $scope.toggle = toggle;
        $scope.isChoicesVisible = isChoicesVisible;
        $scope.isHelperVisible = isHelperVisible;
        $scope.isSelected = isSelected;
        $scope.filterNeeded = filterNeeded;
        $scope.getSelectedElements = getSelectedElements;
        $scope.getSelectedTemplate = getSelectedTemplate;
        $scope.hasNoResults = hasNoResults;
    }])
    .directive('lxSelect', function()
    {
        return {
            restrict: 'E',
            controller: 'LxSelectController',
            scope: {
                selected: '=',
                placeholder: '@',
                choices: '=',
                loading: '@',
                minLength: '@',
                allowClear: '@',
                change: '&', // Parameters: newValue, oldValue
                filter: '&' // Parameters: newValue, oldValue
            },
            templateUrl: 'lumx.select.html',
            transclude: true,
            replace: true,
            link: function(scope, element, attrs, ctrl)
            {
                ctrl.init(element, attrs);
                scope.data = {
                    filter: ''
                };
            }
        };
    })
    .directive('lxSelectSelected', function()
    {
        return {
            restrict: 'E',
            require: '^lxSelect',
            templateUrl: 'lumx.select_selected.html',
            transclude: true,
            link: function(scope, element, attrs, ctrl, transclude)
            {
                ctrl.registerTransclude(transclude);
                scope.data = ctrl.getScope();
            }
        };
    })
    .directive('lxSelectChoices', function()
    {
        return {
            restrict: 'E',
            require: '^lxSelect',
            templateUrl: 'lumx.select_choices.html',
            transclude: true,
            link: function(scope, element, attrs, ctrl)
            {
                scope.data = ctrl.getScope();
            }
        };
    });
<|endoftext|>


<commit_before>/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 8] */

'use strict'

const expect = require('chai').expect
const dagPB = require('ipld-dag-pb')
const dagCBOR = require('ipld-dag-cbor')
const series = require('async/series')
const pull = require('pull-stream')

module.exports = (common) => {
  describe.only('.dag.resolve', () => {
    let ipfs
    let nodePb
    let nodeCbor
    let cidPb
    let cidCbor

    before((done) => {
      common.setup((err, factory) => {
        expect(err).to.not.exist
        factory.spawnNode((err, node) => {
          expect(err).to.not.exist
          ipfs = node
          done()
        })
      })
    })

    after((done) => {
      common.teardown(done)
    })

    it('populate', (done) => {
      series([
        (cb) => {
          dagPB.DAGNode.create(new Buffer('I am inside a Protobuf'), (err, node) => {
            expect(err).to.not.exist
            nodePb = node
            cb()
          })
        },
        (cb) => {
          dagPB.util.cid(nodePb, (err, cid) => {
            expect(err).to.not.exist
            cidPb = cid
            cb()
          })
        },
        (cb) => {
          nodeCbor = {
            someData: 'I am inside a Cbor object',
            pb: { '/': cidPb.toBaseEncodedString() }
          }

          dagCBOR.util.cid(nodeCbor, (err, cid) => {
            expect(err).to.not.exist
            cidCbor = cid
            console.log(nodeCbor)
            cb()
          })
        }
      ], store)

      function store () {
        pull(
          pull.values([
            { node: nodePb, multicodec: 'dag-pb', hashAlg: 'sha2-256' },
            { node: nodeCbor, multicodec: 'dag-cbor', hashAlg: 'sha2-256' }
          ]),
          pull.asyncMap((el, cb) => {
            ipfs.dag.put(el.node, el.multicodec, el.hashAlg, (err) => {
              if (err) {
                console.log(err)
              }
              console.log('put', el.multicodec)

              cb()
            })
          }),
          pull.onEnd(done)
        )
      }
    })

    describe('callback API', () => {
      describe('.resolve', () => {
        it('dag-pb get the node', (done) => {
          ipfs.dag.resolve(cidPb, '/', (err, result) => {
            expect(err).to.not.exist

            dagPB.util.cid(result, (err, cid) => {
              expect(err).to.not.exist
              expect(cid).to.eql(cidPb)
              done()
            })
          })
        })

        it('dag-pb local scope', (done) => {
          ipfs.dag.resolve(cidPb, 'data', (err, result) => {
            expect(err).to.not.exist
            expect(result).to.eql(new Buffer('I am inside a Protobuf'))
            done()
          })
        })

        it.skip('dag-pb one level', (done) => {})
        it.skip('dag-pb two levels', (done) => {})

        it('dag-cbor get the node', (done) => {
          ipfs.dag.get(cidCbor, (err, result) => {
          // ipfs.dag.resolve(cidCbor, '/', (err, result) => {
            expect(err).to.not.exist

            console.log('get the node')

            dagCBOR.util.cid(result, (err, cid) => {
              expect(err).to.not.exist
              expect(cid).to.eql(cidCbor)
              done()
            })
          })
        })

        it('dag-cbor local scope', (done) => {
          ipfs.dag.resolve(cidCbor, 'someData', (err, result) => {
            expect(err).to.not.exist
            expect(result).to.eql('I am inside a Cbor object')
            done()
          })
        })

        it.skip('dag-cbor one level', (done) => {})
        it.skip('dag-cbor two levels', (done) => {})
        it.skip('from dag-pb to dag-cbor', (done) => {})

        it('from dag-cbor to dag-pb', (done) => {
          ipfs.dag.resolve(cidCbor, 'pb/data', (err, result) => {
            expect(err).to.not.exist
            expect(result).to.eql(new Buffer('I am inside a Protobuf'))
            done()
          })
        })
      })
    })

    describe('promise API', () => {
      describe('.resolve', () => {})
    })
  })
}
<commit_msg>test: polish dag-resolve tests<commit_after>/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 8] */

'use strict'

const expect = require('chai').expect
const dagPB = require('ipld-dag-pb')
const dagCBOR = require('ipld-dag-cbor')
const series = require('async/series')
const pull = require('pull-stream')

module.exports = (common) => {
  describe('.dag.resolve', () => {
    let ipfs
    let nodePb
    let nodeCbor
    let cidPb
    let cidCbor

    before((done) => {
      common.setup((err, factory) => {
        expect(err).to.not.exist
        factory.spawnNode((err, node) => {
          expect(err).to.not.exist
          ipfs = node
          done()
        })
      })
    })

    after((done) => {
      common.teardown(done)
    })

    it('populate', (done) => {
      series([
        (cb) => {
          dagPB.DAGNode.create(new Buffer('I am inside a Protobuf'), (err, node) => {
            expect(err).to.not.exist
            nodePb = node
            cb()
          })
        },
        (cb) => {
          dagPB.util.cid(nodePb, (err, cid) => {
            expect(err).to.not.exist
            cidPb = cid
            cb()
          })
        },
        (cb) => {
          nodeCbor = {
            someData: 'I am inside a Cbor object',
            pb: { '/': cidPb.toBaseEncodedString() }
          }

          dagCBOR.util.cid(nodeCbor, (err, cid) => {
            expect(err).to.not.exist
            cidCbor = cid
            cb()
          })
        }
      ], store)

      function store () {
        pull(
          pull.values([
            { node: nodePb, multicodec: 'dag-pb', hashAlg: 'sha2-256' },
            { node: nodeCbor, multicodec: 'dag-cbor', hashAlg: 'sha2-256' }
          ]),
          pull.asyncMap((el, cb) => {
            ipfs.dag.put(el.node, el.multicodec, el.hashAlg, cb)
          }),
          pull.onEnd(done)
        )
      }
    })

    describe('callback API', () => {
      describe('.resolve', () => {
        it('dag-pb get the node', (done) => {
          ipfs.dag.resolve(cidPb, '/', (err, result) => {
            expect(err).to.not.exist

            dagPB.util.cid(result, (err, cid) => {
              expect(err).to.not.exist
              expect(cid).to.eql(cidPb)
              done()
            })
          })
        })

        it('dag-pb local scope', (done) => {
          ipfs.dag.resolve(cidPb, 'data', (err, result) => {
            expect(err).to.not.exist
            expect(result).to.eql(new Buffer('I am inside a Protobuf'))
            done()
          })
        })

        it.skip('dag-pb one level', (done) => {})
        it.skip('dag-pb two levels', (done) => {})

        it('dag-cbor get the node', (done) => {
          ipfs.dag.resolve(cidCbor, '/', (err, result) => {
            expect(err).to.not.exist

            dagCBOR.util.cid(result, (err, cid) => {
              expect(err).to.not.exist
              expect(cid).to.eql(cidCbor)
              done()
            })
          })
        })

        it('dag-cbor local scope', (done) => {
          ipfs.dag.resolve(cidCbor, 'someData', (err, result) => {
            expect(err).to.not.exist
            expect(result).to.eql('I am inside a Cbor object')
            done()
          })
        })

        it.skip('dag-cbor one level', (done) => {})
        it.skip('dag-cbor two levels', (done) => {})
        it.skip('from dag-pb to dag-cbor', (done) => {})

        it('from dag-cbor to dag-pb', (done) => {
          ipfs.dag.resolve(cidCbor, 'pb/data', (err, result) => {
            expect(err).to.not.exist
            expect(result).to.eql(new Buffer('I am inside a Protobuf'))
            done()
          })
        })
      })
    })

    describe('promise API', () => {
      describe('.resolve', () => {})
    })
  })
}
<|endoftext|>


<commit_before>define([
  'Class', 'uri', 'moment', 'underscore',
  'map/services/DataService'
], function (Class, UriTemplate, moment, _, ds) {

  'use strict';

  var REQUEST_ID = 'GladDateService:fetchDates';

  var URL = window.gfw.config.GFW_API_HOST + "/forest-change/glad-alerts/latest";

  var GladDateService = Class.extend({

    init: function(options) {
      this.options = options || {};
      this._defineRequests();
    },

    _defineRequests: function() {
      var endOfDay = moment().endOf('day'),
          secondsToEndOfDay = endOfDay.diff(moment()) / 1000;

      var config = {
        cache: {type: 'persist', duration: secondsToEndOfDay, unit: 'seconds'},
        url: URL,
        type: 'GET'
      };

      ds.define(REQUEST_ID, config);
    },

    fetchDates: function() {
      var deferred = new $.Deferred();

      var onSuccess = function(result) {
        deferred.resolve(_.pick(result, 'max_date', 'counts'));
      };

      var config = {
        resourceId: REQUEST_ID,
        success: onSuccess,
        error: deferred.reject
      };

      ds.request(config);

      return deferred.promise();
    }

  });

  return GladDateService;

});
<commit_msg>Fix: GLAD - Removed cache for max available data date request<commit_after>define([
  'Class', 'uri', 'moment', 'underscore',
  'map/services/DataService'
], function (Class, UriTemplate, moment, _, ds) {

  'use strict';

  var REQUEST_ID = 'GladDateService:fetchDates';

  var URL = window.gfw.config.GFW_API_HOST + "/forest-change/glad-alerts/latest";

  var GladDateService = Class.extend({

    init: function(options) {
      this.options = options || {};
      this._defineRequests();
    },

    _defineRequests: function() {
      var config = {
        cache: false,
        url: URL,
        type: 'GET'
      };

      ds.define(REQUEST_ID, config);
    },

    fetchDates: function() {
      var deferred = new $.Deferred();

      var onSuccess = function(result) {
        deferred.resolve(_.pick(result, 'max_date', 'counts'));
      };

      var config = {
        resourceId: REQUEST_ID,
        success: onSuccess,
        error: deferred.reject
      };

      ds.request(config);

      return deferred.promise();
    }

  });

  return GladDateService;

});
<|endoftext|>


<commit_before>
export function init(main_div){
  if (!(main_div instanceof HTMLElement)){
    main_div = document.getElementById(main_div.startsWith("#") ? main_div.slice(1) : main_div);
  }

    main_div.innerHTML = `

        1. Choose a dataset

	<button class="btn btn-main" id="mixed_model_analysis_prepare_button">Go!</button>

    `;

}
<commit_msg>remove old analysis detail mason file.<commit_after><|endoftext|>


<commit_before>// Helpers.FormControls.getSelect
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getSelect(options) {
    var _options = options || '';
    return ['<select name="" id="">', _options, '</select>'].join('');
  }

  Module.select = {
    getSelect: getSelect
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

// Helpers.FormControls.getInput
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getInput(config) {
    var _config = $.extend({}, {
      type: 'text',
      classes: '',
      id: '',
      value: '',
      name: ''
    }, config);
    return ['<input class="form-control ' + _config.classes + '" type="' + _config.type + '" name="' + _config.name + '" id="' + _config.id + '" value="' + _config.value + '" />'].join('');
  }

  Module.input = {
    getInput: getInput
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

// Helpers.FormControls.getOptions
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getOptions(collection, selected) {
    var def = $.Deferred();
    var optionsArray = [];
    var collectioSize;
    var option;
    selected = selected || {
      value: 'miss-match'
    };
    if (!collection) {
      throw Error('Missing param: collection');
    }

    optionsArray.push(new Option('Please select', '').outerHTML);
    collectionSize = collection.length;

    collection.forEach(function(obj, idx) {
      option = new Option(obj.name, obj.id, (obj[selected.prop] === selected.value));
      option.dataset.postcode = obj.postcode;
      optionsArray.push(option.outerHTML);

      if (collectionSize - 1 === idx) {
        def.resolve(optionsArray);
      }
    });
    return def.promise();
  }

  Module.selectOptions = {
    getOptions: getOptions
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  Module = {
    select: Module.select,
    selectOptions: Module.selectOptions,
    input: Module.input,
    getInput: Module.input.getInput,
    getSelect: Module.select.getSelect,
    getOptions: Module.selectOptions.getOptions,

  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));
<commit_msg>Add getGovUkDate helper<commit_after>// Helpers.FormControls.getSelect
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getSelect(options) {
    var _options = options || '';
    return ['<select name="" id="">', _options, '</select>'].join('');
  }

  Module.select = {
    getSelect: getSelect
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

// Helpers.FormControls.getInput
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getInput(config) {
    var _config = $.extend({}, {
      type: 'text',
      classes: '',
      id: '',
      value: '',
      name: ''
    }, config);
    return ['<input class="form-control ' + _config.classes + '" type="' + _config.type + '" name="' + _config.name + '" id="' + _config.id + '" value="' + _config.value + '" />'].join('');
  }

  Module.input = {
    getInput: getInput
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

// Helpers.FormControls.getOptions
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getOptions(collection, selected) {
    var def = $.Deferred();
    var optionsArray = [];
    var collectionSize;
    var option;
    selected = selected || {
      value: 'miss-match'
    };
    if (!collection) {
      throw Error('Missing param: collection');
    }

    optionsArray.push(new Option('Please select', '').outerHTML);
    collectionSize = collection.length;

    collection.forEach(function(obj, idx) {
      option = new Option(obj.name, obj.id, (obj[selected.prop] === selected.value));
      option.dataset.postcode = obj.postcode;
      optionsArray.push(option.outerHTML);

      if (collectionSize - 1 === idx) {
        def.resolve(optionsArray);
      }
    });
    return def.promise();
  }

  Module.selectOptions = {
    getOptions: getOptions
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

// Helpers.FormControls.getGovUkDate
(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  function getGovUkDate(context) {
    var dateArray = [];
    $(context).first('.gov_uk_date:visible').find('input[type=number]').is(function (index, element) {
      dateArray.push($(element).val());
    });

    return new Date(dateArray.reverse().join('-'));
  }

  Module.govUkDate = {
    getGovUkDate: getGovUkDate
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));

(function(exports, $) {
  var Module = exports.Helpers.FormControls || {};

  Module = {
    select: Module.select,
    selectOptions: Module.selectOptions,
    input: Module.input,
    getInput: Module.input.getInput,
    getSelect: Module.select.getSelect,
    getOptions: Module.selectOptions.getOptions,
    getGovUkDate: Module.govUkDate.getGovUkDate
  };

  exports.Helpers.FormControls = Module;
}(moj, jQuery));
<|endoftext|>


<commit_before>define(['logger', 'tracker', 'underscore', 'jquery', 'backbone', 'voc',
        'text!templates/toolbar/episode.tpl',
        'data/episode/EpisodeData', 'data/episode/UserData', 'view/toolbar/EpisodeListingView'], function(Logger, tracker, _, $, Backbone, Voc, EpisodeTemplate, EpisodeData, UserData, EpisodeListingView){
    return Backbone.View.extend({
        episodeViews: [],
        events: {
            'keypress input[name="label"]' : 'updateOnEnter',
            'blur input[name="label"]' : 'changeLabel',
            'keypress textarea[name="description"]' : 'updateOnEnter',
            'blur textarea[name="description"]' : 'changeDescription',
            'change input[name="sharetype"]' : 'shareTypeChanged',
            'click input[name="share"]' : 'shareEpisode',
            'click .selectedUser > span' : 'removeSelectedUser',
            'click input[name="onlyselected"]' : 'clickOnlySelected'
        },
        LOG: Logger.get('EpisodeToolbarView'),
        initialize: function() {
            this.model.on('change:' + this.model.vie.namespaces.uri(Voc.currentVersion), this.episodeVersionChanged, this);
            this.model.on('change:' + this.model.vie.namespaces.uri(Voc.hasEpisode), this.changeEpisodeSet, this);
            this.searchableUsers = [];
            this.selectedUsers = [];
            var that = this;
            UserData.fetchAllUsers().then(function(users) {
                _.each(users, function(user) {
                    that.searchableUsers.push({
                        label: user.label,
                        value: user.id
                    });
                });
            });
        },
        episodeVersionChanged: function() {
            this.render();
        },
        getCurrentVersion: function() {
            return this.model.get(Voc.currentVersion);
        },
        getCurrentEpisode: function() {
            var version = this.getCurrentVersion();
            return version.get(Voc.belongsToEpisode);
        },
        render: function() {
            var that = this;
            this.$el.empty();
            if( !this.getCurrentVersion() || !this.getCurrentEpisode() ) {
                // ... empty the toolbar content
                this.$el.html("No episode");
                return;
            }
            this.$el.html(_.template(EpisodeTemplate, this.getEpisodeViewData()));

            // Initialize user select autocomplete
            this.$el.find('input[name="sharewith"]').autocomplete({
                source: this.searchableUsers,
                select: function(event, ui) {
                    event.preventDefault();
                    that.addSelectedUser(event, ui, this);
                }
            });

            this.addOrUpdateEpisodeViews();
        },
        addOrUpdateEpisodeViews: function() {
            var that = this,
                box = this.$el.find('.toolbarSectionEpisodes .myEpisodes .episodeListing'),
                episodes = this.getEpisodes();
            _.each(this.episodeViews, function(view) {
                view.remove();
            });
            this.episodeViews = [];
            _.each(episodes, function(episode) {
                var view = new EpisodeListingView({
                    model: episode
                });
                box.append(view.render().$el);
                that.episodeViews.push(view);
            });
        },
        updateOnEnter: function(e) {
            if (e.keyCode == 13) {
                this.LOG.debug('updateOnEnter', e);
                if ( $(e.currentTarget).attr('name') === 'label' || $(e.currentTarget).attr('name') === 'description' ) {
                    $(e.currentTarget).blur();
                }

            }
        },
        getEpisodeViewData: function() {
            var episode = this.getCurrentEpisode();
            return {
                entity : {
                    label : episode.get(Voc.label),
                    description : episode.get(Voc.description)
                }
            };
        },
        changeLabel: function(e) {
            var that = this,
            currentTarget = $(e.currentTarget),
            label = currentTarget.val(),
            episode = this.getCurrentEpisode();

            if( episode.get(Voc.label) == label) return;
            this.LOG.debug('changeLabel', label);
            // Make sure to set user_initiated flag
            episode.set(Voc.label, label, {
                'error' : function() {
                    that.$el.find('input[name="label"]').effect("shake");
                },
                'user_initiated' : true
            });
        },
        changeDescription: function(e) {
            var that = this,
                currentTarget = $(e.currentTarget),
                description = currentTarget.val(),
                episode = this.getCurrentEpisode();

            if( episode.get(Voc.description) == description) return;
            this.LOG.debug('changeDescription', description);
            // Make sure to set user_initiated flag
            episode.set(Voc.description, description, {
                'error' : function() {
                    that.$el.find('textarea[name="description"]').effect("shake");
                },
                'user_initiated' : true
            });

        },
        shareTypeChanged: function(e) {
            if ( $(e.currentTarget).val() === 'coediting' ) {
                var onlyselected = this.$el.find('input[name="onlyselected"]');
                if ( onlyselected.is(':checked') ) {
                    onlyselected.trigger('click');
                }
                onlyselected.prop('disabled', true)
            } else if ( $(e.currentTarget).val() === 'separatecopy' ) {
                this.$el.find('input[name="onlyselected"]').prop('disabled', false);
            }
        },
        shareEpisode: function(e) {
            var that = this,
                shareType = this.$el.find('input[name="sharetype"]:checked').val(),
                onlySelected = this.$el.find('input[name="onlyselected"]').is(':checked'),
                notificationText = this.$el.find('textarea[name="notificationtext"]').val(),
                users = [],
                excluded = [],
                episode = this.getCurrentEpisode();

            if ( _.isEmpty(notificationText.trim()) ) {
                alert('Some required fields are empty');
                return false;
            }

            if ( this.selectedUsers.length < 1 ) {
                alert('No users selected');
                return false;
            }

            if ( shareType === 'coediting' ) {
                EpisodeData.shareEpisode(episode, this.selectedUsers, notificationText);
                this._cleanUpAfterSharing();
            } else if ( shareType === 'separatecopy' ) {
                // Determine if some bits need to be excluded
                if ( onlySelected === true ) {
                    this.LOG.debug('Only selected bits');
                    _.each(this.$el.find('select[name="only"] option:not(:selected)'), function(element) {
                        excluded.push($(element).val());
                    });
                }
                EpisodeData.copyEpisode(episode, this.selectedUsers, excluded, notificationText);
                this._cleanUpAfterSharing();
            } else {
                this.LOG.debug('Invalid share type');
            }
        },
        _cleanUpAfterSharing: function() {
            this.$el.find('#coediting').trigger('click');
            this.$el.find('input[name="sharewith"]').val('');
            this.$el.find('textarea[name="notificationtext"]').val('');
            this.$el.find('.selectedUser').remove();
            this.$el.find('select[name="only"]').remove();
            this.selectedUsers = [];
        },
        addSelectedUser: function(event, ui, autocomplete) {
            if ( _.indexOf(this.selectedUsers, ui.item.value) === -1 ) {
                this.selectedUsers.push(ui.item.value);
                $(autocomplete).val(ui.item.label);
                $(autocomplete).parent().append('
' + ui.item.label + ' x
');
            }
        },
        removeSelectedUser: function(e) {
            var removable = $(e.currentTarget).parent();
            delete this.selectedUsers[_.indexOf(this.selectedUsers, removable.data('value'))];
            removable.remove();
        },
        getCurrentEntitiesAndCircles: function() {
            var response = {
                circles: [],
                entities: []
            },
            version = this.getCurrentVersion(),
            widgets = version.get(Voc.hasWidget);
            _.each(widgets, function(widget) {
                if ( widget.get('@type').isof(Voc.ORGANIZE) ) {
                    response.circles = widget.get(Voc.hasCircle) || [];
                    if( !_.isArray(response.circles)) response.circles = [response.circles];
                    response.entities = widget.get(Voc.hasEntity) || [];
                    if( !_.isArray(response.entities)) response.entities = [response.entities];
                }
            });

            return response;
        },
        clickOnlySelected: function(e) {
            var current = this.getCurrentEntitiesAndCircles();
            if ( $(e.currentTarget).is(':checked') ) {
                // Add and render
                var select = $('<select name="only" multiple="multiple" class="shareBitsOnly"></select>'),
                    circles = $('<optgroup label="Circles"></optgroup>'),
                    entities = $('<optgroup label="Entities"></optgrpup>');
                _.each(current.circles, function(circle) {
                    circles.append('<option value="' + circle.attributes['@subject'] + '">' + circle.get(Voc.Label) + '</option>');
                });
                _.each(current.entities, function(orgaentity) {
                    var entity = orgaentity.get(Voc.hasResource);
                    entities.append('<option value="' + orgaentity.attributes['@subject']+ '">' + entity.get(Voc.label) + '</option>');
                });
                select.append(circles);
                select.append(entities);
                $(e.currentTarget).after(select);
            } else {
                this.$el.find('select[name="only"]').remove();
            }
        },
        getEpisodes: function() {
            var episodes = this.model.get(Voc.hasEpisode) || [];
            if( !_.isArray(episodes)) episodes = [episodes];
            return episodes;
        }
    });
});
<commit_msg>LL-293 #close Episode search implemented.<commit_after>define(['logger', 'tracker', 'underscore', 'jquery', 'backbone', 'voc',
        'text!templates/toolbar/episode.tpl',
        'data/episode/EpisodeData', 'data/episode/UserData', 'view/toolbar/EpisodeListingView'], function(Logger, tracker, _, $, Backbone, Voc, EpisodeTemplate, EpisodeData, UserData, EpisodeListingView){
    return Backbone.View.extend({
        episodeViews: [],
        events: {
            'keypress input[name="label"]' : 'updateOnEnter',
            'blur input[name="label"]' : 'changeLabel',
            'keypress textarea[name="description"]' : 'updateOnEnter',
            'blur textarea[name="description"]' : 'changeDescription',
            'change input[name="sharetype"]' : 'shareTypeChanged',
            'click input[name="share"]' : 'shareEpisode',
            'click .selectedUser > span' : 'removeSelectedUser',
            'click input[name="onlyselected"]' : 'clickOnlySelected',
            'keypress input[name="search"]' : 'updateOnEnter'
        },
        LOG: Logger.get('EpisodeToolbarView'),
        initialize: function() {
            this.model.on('change:' + this.model.vie.namespaces.uri(Voc.currentVersion), this.episodeVersionChanged, this);
            this.model.on('change:' + this.model.vie.namespaces.uri(Voc.hasEpisode), this.changeEpisodeSet, this);
            this.searchableUsers = [];
            this.selectedUsers = [];
            var that = this;
            UserData.fetchAllUsers().then(function(users) {
                _.each(users, function(user) {
                    that.searchableUsers.push({
                        label: user.label,
                        value: user.id
                    });
                });
            });
        },
        episodeVersionChanged: function() {
            this.render();
        },
        getCurrentVersion: function() {
            return this.model.get(Voc.currentVersion);
        },
        getCurrentEpisode: function() {
            var version = this.getCurrentVersion();
            return version.get(Voc.belongsToEpisode);
        },
        render: function() {
            var that = this;
            this.$el.empty();
            if( !this.getCurrentVersion() || !this.getCurrentEpisode() ) {
                // ... empty the toolbar content
                this.$el.html("No episode");
                return;
            }
            this.$el.html(_.template(EpisodeTemplate, this.getEpisodeViewData()));

            // Initialize user select autocomplete
            this.$el.find('input[name="sharewith"]').autocomplete({
                source: this.searchableUsers,
                select: function(event, ui) {
                    event.preventDefault();
                    that.addSelectedUser(event, ui, this);
                }
            });

            this.addOrUpdateEpisodeViews();
        },
        addOrUpdateEpisodeViews: function(episodes) {
            var that = this,
                box = this.$el.find('.toolbarSectionEpisodes .myEpisodes .episodeListing');
            if ( !_.isArray(episodes) ) {
                episodes = this.getEpisodes();
            }
            _.each(this.episodeViews, function(view) {
                view.remove();
            });
            this.episodeViews = [];
            _.each(episodes, function(episode) {
                var view = new EpisodeListingView({
                    model: episode
                });
                box.append(view.render().$el);
                that.episodeViews.push(view);
            });
        },
        updateOnEnter: function(e) {
            if (e.keyCode == 13) {
                this.LOG.debug('updateOnEnter', e);
                var currentTarget = $(e.currentTarget);
                if ( currentTarget.attr('name') === 'label' || currentTarget.attr('name') === 'description' ) {
                    currentTarget.blur();
                } else if ( currentTarget.attr('name') === 'search' ) {
                    this.addOrUpdateEpisodeViews( this.searchEpisodes(currentTarget.val()) );
                }

            }
        },
        getEpisodeViewData: function() {
            var episode = this.getCurrentEpisode();
            return {
                entity : {
                    label : episode.get(Voc.label),
                    description : episode.get(Voc.description)
                }
            };
        },
        changeLabel: function(e) {
            var that = this,
            currentTarget = $(e.currentTarget),
            label = currentTarget.val(),
            episode = this.getCurrentEpisode();

            if( episode.get(Voc.label) == label) return;
            this.LOG.debug('changeLabel', label);
            // Make sure to set user_initiated flag
            episode.set(Voc.label, label, {
                'error' : function() {
                    that.$el.find('input[name="label"]').effect("shake");
                },
                'user_initiated' : true
            });
        },
        changeDescription: function(e) {
            var that = this,
                currentTarget = $(e.currentTarget),
                description = currentTarget.val(),
                episode = this.getCurrentEpisode();

            if( episode.get(Voc.description) == description) return;
            this.LOG.debug('changeDescription', description);
            // Make sure to set user_initiated flag
            episode.set(Voc.description, description, {
                'error' : function() {
                    that.$el.find('textarea[name="description"]').effect("shake");
                },
                'user_initiated' : true
            });

        },
        shareTypeChanged: function(e) {
            if ( $(e.currentTarget).val() === 'coediting' ) {
                var onlyselected = this.$el.find('input[name="onlyselected"]');
                if ( onlyselected.is(':checked') ) {
                    onlyselected.trigger('click');
                }
                onlyselected.prop('disabled', true)
            } else if ( $(e.currentTarget).val() === 'separatecopy' ) {
                this.$el.find('input[name="onlyselected"]').prop('disabled', false);
            }
        },
        shareEpisode: function(e) {
            var that = this,
                shareType = this.$el.find('input[name="sharetype"]:checked').val(),
                onlySelected = this.$el.find('input[name="onlyselected"]').is(':checked'),
                notificationText = this.$el.find('textarea[name="notificationtext"]').val(),
                users = [],
                excluded = [],
                episode = this.getCurrentEpisode();

            if ( _.isEmpty(notificationText.trim()) ) {
                alert('Some required fields are empty');
                return false;
            }

            if ( this.selectedUsers.length < 1 ) {
                alert('No users selected');
                return false;
            }

            if ( shareType === 'coediting' ) {
                EpisodeData.shareEpisode(episode, this.selectedUsers, notificationText);
                this._cleanUpAfterSharing();
            } else if ( shareType === 'separatecopy' ) {
                // Determine if some bits need to be excluded
                if ( onlySelected === true ) {
                    this.LOG.debug('Only selected bits');
                    _.each(this.$el.find('select[name="only"] option:not(:selected)'), function(element) {
                        excluded.push($(element).val());
                    });
                }
                EpisodeData.copyEpisode(episode, this.selectedUsers, excluded, notificationText);
                this._cleanUpAfterSharing();
            } else {
                this.LOG.debug('Invalid share type');
            }
        },
        _cleanUpAfterSharing: function() {
            this.$el.find('#coediting').trigger('click');
            this.$el.find('input[name="sharewith"]').val('');
            this.$el.find('textarea[name="notificationtext"]').val('');
            this.$el.find('.selectedUser').remove();
            this.$el.find('select[name="only"]').remove();
            this.selectedUsers = [];
        },
        addSelectedUser: function(event, ui, autocomplete) {
            if ( _.indexOf(this.selectedUsers, ui.item.value) === -1 ) {
                this.selectedUsers.push(ui.item.value);
                $(autocomplete).val(ui.item.label);
                $(autocomplete).parent().append('
' + ui.item.label + ' x
');
            }
        },
        removeSelectedUser: function(e) {
            var removable = $(e.currentTarget).parent();
            delete this.selectedUsers[_.indexOf(this.selectedUsers, removable.data('value'))];
            removable.remove();
        },
        getCurrentEntitiesAndCircles: function() {
            var response = {
                circles: [],
                entities: []
            },
            version = this.getCurrentVersion(),
            widgets = version.get(Voc.hasWidget);
            _.each(widgets, function(widget) {
                if ( widget.get('@type').isof(Voc.ORGANIZE) ) {
                    response.circles = widget.get(Voc.hasCircle) || [];
                    if( !_.isArray(response.circles)) response.circles = [response.circles];
                    response.entities = widget.get(Voc.hasEntity) || [];
                    if( !_.isArray(response.entities)) response.entities = [response.entities];
                }
            });

            return response;
        },
        clickOnlySelected: function(e) {
            var current = this.getCurrentEntitiesAndCircles();
            if ( $(e.currentTarget).is(':checked') ) {
                // Add and render
                var select = $('<select name="only" multiple="multiple" class="shareBitsOnly"></select>'),
                    circles = $('<optgroup label="Circles"></optgroup>'),
                    entities = $('<optgroup label="Entities"></optgrpup>');
                _.each(current.circles, function(circle) {
                    circles.append('<option value="' + circle.attributes['@subject'] + '">' + circle.get(Voc.Label) + '</option>');
                });
                _.each(current.entities, function(orgaentity) {
                    var entity = orgaentity.get(Voc.hasResource);
                    entities.append('<option value="' + orgaentity.attributes['@subject']+ '">' + entity.get(Voc.label) + '</option>');
                });
                select.append(circles);
                select.append(entities);
                $(e.currentTarget).after(select);
            } else {
                this.$el.find('select[name="only"]').remove();
            }
        },
        getEpisodes: function() {
            var episodes = this.model.get(Voc.hasEpisode) || [];
            if( !_.isArray(episodes)) episodes = [episodes];
            return episodes;
        },
        searchEpisodes: function(searchable) {
            var regexp = new RegExp(searchable, 'i'),
                episodes = this.getEpisodes(),
                returned = [];

            searchable = searchable.trim();

            if ( _.isEmpty(searchable) ) return episodes;

            _.each(episodes, function(episode) {
                var label = episode.get(Voc.label),
                    description = episode.get(Voc.description);
                if ( label.search(regexp) !== -1 || description.search(regexp) !== -1 ) {
                    returned.push(episode);
                }
            });

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