<commit_before>/**
 * @overview tests for for ccm component for interpreting JavaScript expressions
 * @author André Kless <andre.kless@web.de> 2017
 * @license The MIT License (MIT)
 */

ccm.files[ 'ccm.eval.tests.js' ] = {
  setup: function ( suite, callback ) {
    suite.container = document.createElement( 'div' );
    document.body.appendChild( suite.container );
    suite.ccm.component( '../../ccm-components/eval/ccm.eval.js', { element: suite.container }, function ( component ) {
      suite.component = component;
      callback();
    } );
  },
  fundamental: {
    setup: function ( suite, callback ) {
      suite.component.instance( function ( instance ) {
        suite.instance = instance;
        callback();
      } );
    },
    tests: {
      componentName: function ( suite ) {
        suite.assertSame( 'eval', suite.instance.component.name );
      },
      frameworkVersion: function ( suite ) {
        suite.assertEquals( '8.0.0', suite.instance.ccm.version() );
      },
      publicInstanceProperties: function ( suite ) {
        suite.assertEquals( [ 'start', 'ccm', 'element', 'id', 'index', 'component' ], Object.keys( suite.instance ) );
      },
      startCallback: function ( suite ) {
        suite.instance.start( suite.passed );
      }
    }
  },
  defaults: {
    setup: function ( suite, callback ) {
      suite.component.start( function ( instance ) {
        suite.instance = instance;
        callback();
      } );
    },
    tests: {
      mainTemplate: function ( suite ) {
        if ( !suite.instance.element.querySelector( '#expression' ) ) return suite.failed( 'missing expression container' );
        suite.passed();
      },
      buttonCaption: function ( suite ) {
        suite.assertEquals( 'Evaluate expression', suite.instance.element.querySelector( 'button' ).innerHTML );
      },
      onFinish: function ( suite ) {
        suite.instance.onfinish = function ( instance, results ) {
          if ( instance !== suite.instance ) return suite.failed( 'incorrect first parameter' );
          if ( results.expression !== '"Hello, World!"' ) return suite.failed( 'wrong expression in result data' );
          if ( results.value !== 'Hello, World!' ) return suite.failed( 'wrong value in result data' );
          suite.passed();
        };
        suite.instance.element.querySelector( 'button' ).click();
      }
    }
  },
  dependencies: {
    tests: {
      loggedInUser: function ( suite ) {
        suite.component.start( {
          user: [ 'ccm.instance', '../../ccm-components/user/ccm.user.js' ],
          onfinish: function ( instance ) {
            suite.assertTrue( instance.user.isLoggedIn() );
          }
        }, function ( instance ) {
          if ( instance.user.isLoggedIn() ) suite.failed( 'user is already logged in' );
          instance.element.querySelector( 'button' ).click();
        } );
      },
      logStartEvent: function ( suite ) {
        suite.component.start( {
          logger: [ 'ccm.instance', '../../ccm-components/log/ccm.log.js', { onfinish: function ( instance, results ) {
            suite.assertSame( 'start', results.event );
          } } ]
        } );
      },
      logFinishEvent: function ( suite ) {
        suite.component.start( {
          logger: [ 'ccm.instance', '../../ccm-components/log/ccm.log.js', {
            events: { finish: true },
            onfinish: function ( instance, results ) {
              suite.assertSame( 'finish', results.event );
            }
          } ]
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      }
    }
  },
  json_parse: {
    tests: {
      valid: function ( suite ) {
        suite.component.start( {
          expression: '{ "foo": "bar" }',
          json_parse: true,
          onfinish: function ( instance, results ) {
            suite.assertEquals( { foo: 'bar' }, results.value );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      },
      invalid: function ( suite ) {
        suite.component.start( {
          expression: "{ foo: 'bar' }",
          json_parse: true,
          onfinish: function ( instance, results ) {
            suite.assertEquals( undefined, results.value );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      },
      functionsNotParsable: function ( suite ) {
        suite.component.start( {
          expression: 'function () {}',
          json_parse: true,
          onfinish: function ( instance, results ) {
            suite.assertEquals( undefined, results.value );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      },
      evalIntertretsFunctions: function ( suite ) {
        suite.component.start( {
          expression: 'function () {}',
          json_parse: false,
          onfinish: function ( instance, results ) {
            if ( typeof results.value !== 'function' )
              return suite.failed( 'result value is not a function' );
            suite.assertEquals( 'function () {}', results.value.toString() );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      }
    }
  },
  finally: function ( suite, callback ) {
    document.body.removeChild( suite.container );
    callback();
  }
};

ccm.components.testsuite.eval = ccm.files[ 'ccm.eval.tests.js' ];<commit_msg>minor change in ccm.eval.tests.js<commit_after>/**
 * @overview tests for ccm component for interpreting JavaScript expressions
 * @author André Kless <andre.kless@web.de> 2017
 * @license The MIT License (MIT)
 */

ccm.files[ 'ccm.eval.tests.js' ] = {
  setup: function ( suite, callback ) {
    suite.container = document.createElement( 'div' );
    document.body.appendChild( suite.container );
    suite.ccm.component( '../../ccm-components/eval/ccm.eval.js', { element: suite.container }, function ( component ) {
      suite.component = component;
      callback();
    } );
  },
  fundamental: {
    setup: function ( suite, callback ) {
      suite.component.instance( function ( instance ) {
        suite.instance = instance;
        callback();
      } );
    },
    tests: {
      componentName: function ( suite ) {
        suite.assertSame( 'eval', suite.instance.component.name );
      },
      frameworkVersion: function ( suite ) {
        suite.assertEquals( '8.0.0', suite.instance.ccm.version() );
      },
      publicInstanceProperties: function ( suite ) {
        suite.assertEquals( [ 'start', 'ccm', 'element', 'id', 'index', 'component' ], Object.keys( suite.instance ) );
      },
      startCallback: function ( suite ) {
        suite.instance.start( suite.passed );
      }
    }
  },
  defaults: {
    setup: function ( suite, callback ) {
      suite.component.start( function ( instance ) {
        suite.instance = instance;
        callback();
      } );
    },
    tests: {
      mainTemplate: function ( suite ) {
        if ( !suite.instance.element.querySelector( '#expression' ) ) return suite.failed( 'missing expression container' );
        suite.passed();
      },
      buttonCaption: function ( suite ) {
        suite.assertEquals( 'Evaluate expression', suite.instance.element.querySelector( 'button' ).innerHTML );
      },
      onFinish: function ( suite ) {
        suite.instance.onfinish = function ( instance, results ) {
          if ( instance !== suite.instance ) return suite.failed( 'incorrect first parameter' );
          if ( results.expression !== '"Hello, World!"' ) return suite.failed( 'wrong expression in result data' );
          if ( results.value !== 'Hello, World!' ) return suite.failed( 'wrong value in result data' );
          suite.passed();
        };
        suite.instance.element.querySelector( 'button' ).click();
      }
    }
  },
  dependencies: {
    tests: {
      loggedInUser: function ( suite ) {
        suite.component.start( {
          user: [ 'ccm.instance', '../../ccm-components/user/ccm.user.js' ],
          onfinish: function ( instance ) {
            suite.assertTrue( instance.user.isLoggedIn() );
          }
        }, function ( instance ) {
          if ( instance.user.isLoggedIn() ) suite.failed( 'user is already logged in' );
          instance.element.querySelector( 'button' ).click();
        } );
      },
      logStartEvent: function ( suite ) {
        suite.component.start( {
          logger: [ 'ccm.instance', '../../ccm-components/log/ccm.log.js', { onfinish: function ( instance, results ) {
            suite.assertSame( 'start', results.event );
          } } ]
        } );
      },
      logFinishEvent: function ( suite ) {
        suite.component.start( {
          logger: [ 'ccm.instance', '../../ccm-components/log/ccm.log.js', {
            events: { finish: true },
            onfinish: function ( instance, results ) {
              suite.assertSame( 'finish', results.event );
            }
          } ]
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      }
    }
  },
  json_parse: {
    tests: {
      valid: function ( suite ) {
        suite.component.start( {
          expression: '{ "foo": "bar" }',
          json_parse: true,
          onfinish: function ( instance, results ) {
            suite.assertEquals( { foo: 'bar' }, results.value );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      },
      invalid: function ( suite ) {
        suite.component.start( {
          expression: "{ foo: 'bar' }",
          json_parse: true,
          onfinish: function ( instance, results ) {
            suite.assertEquals( undefined, results.value );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      },
      functionsNotParsable: function ( suite ) {
        suite.component.start( {
          expression: 'function () {}',
          json_parse: true,
          onfinish: function ( instance, results ) {
            suite.assertEquals( undefined, results.value );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      },
      evalIntertretsFunctions: function ( suite ) {
        suite.component.start( {
          expression: 'function () {}',
          json_parse: false,
          onfinish: function ( instance, results ) {
            if ( typeof results.value !== 'function' )
              return suite.failed( 'result value is not a function' );
            suite.assertEquals( 'function () {}', results.value.toString() );
          }
        }, function ( instance ) {
          instance.element.querySelector( 'button' ).click();
        } );
      }
    }
  },
  finally: function ( suite, callback ) {
    document.body.removeChild( suite.container );
    callback();
  }
};

ccm.components.testsuite.eval = ccm.files[ 'ccm.eval.tests.js' ];<|endoftext|>


<commit_before>// state of showing the information panel
var infoVis = true;

$(function() {
    // allow tooltip on datapoints
    $("

").css({
        position: "absolute",
        display: "none",
        border: "1px solid #ccc",
        padding: "2px",
        opacity: .9
    }).appendTo("body");
    // assign hover function
    $("#graph").on("plothover", function(event, pos, item) {
        if (item) {
            var itemTime = new Date(item.datapoint[0]);
            var hrs = itemTime.getHours();
            hrs = hrs < 10 ? "0" + hrs : hrs;
            var min = itemTime.getMinutes();
            min = min < 10 ? "0" + min : min;
            var sec = itemTime.getSeconds();
            sec = sec < 10 ? "0" + sec : sec;
            $("#tooltip").html(hrs + ":" + min + ":" + sec + " : " + item.datapoint[1]).css({
                top: item.pageY + 7,
                left: item.pageX + 5
            }).fadeIn(200);
        } else $("#tooltip").hide();
    });
    // toggle the selection
    $("#toggle").click(function() {
        if (infoVis) $("#infopanel").hide(); else $("#infopanel").show();
        infoVis = !infoVis;
    });
});

// link to the web server's IP address for socket connection
var socket = io.connect(location.host);

// the received values
var series = new Array(), sensors = {};

// the selected series to show
var selSeries = new Array();

var color = 0;

var options = {
    series: {
        lines: {
            show: true,
            steps: true
        },
        points: {
            show: false
        }
    },
    grid: {
        hoverable: true
    },
    xaxis: {
        mode: "time",
        timezone: "browser"
    },
    yaxis: {
        min: 0
    }
};

// process socket connection
socket.on("connect", function() {
    var flx;
    socket.on("mqtt", function(msg) {
        // determine topic and payload
        var topic = msg.topic.split("/");
        var payload = msg.payload;
        switch (topic[1]) {
          case "device":
            handle_device(topic, payload);
            break;

          case "sensor":
            handle_sensor(flx, topic, payload);
            break;

          default:
            break;
        }
    });
    // handle the device information
    function handle_device(topic, payload) {
        var deviceID = topic[2];
        if (topic[4] == "flx") flx = JSON.parse(payload);
        if (topic[4] == "sensor") {
            var config = JSON.parse(payload);
            for (var obj in config) {
                var cfg = config[obj];
                if (cfg.enable == "1") {
                    if (sensors[cfg.id] == null) {
                        sensors[cfg.id] = new Object();
                        sensors[cfg.id].id = cfg.id;
                        if (cfg.function != undefined) {
                            sensors[cfg.id].name = cfg.function;
                        } else {
                            sensors[cfg.id].name = cfg.id;
                        }
                        if (cfg.subtype != undefined) sensors[cfg.id].subtype = cfg.subtype;
                        if (cfg.port != undefined) sensors[cfg.id].port = cfg.port[0];
                    } else {
                        if (cfg.function != undefined) sensors[cfg.id].name = cfg.function;
                    }
                }
            }
        }
    }
    socket.emit("subscribe", {
        topic: "/device/+/config/sensor"
    });
    socket.emit("subscribe", {
        topic: "/device/+/config/flx"
    });
    socket.emit("subscribe", {
        topic: "/sensor/+/gauge"
    });
});

// handle the sensor information
function handle_sensor(flx, topic, payload) {
    var sensor = {};
    var msgType = topic[3];
    var sensorId = topic[2];
    if (sensors[sensorId] == null) {
        sensors[sensorId] = new Object();
        sensor.id = sensorId;
        sensor.name = sensorId;
    } else sensor = sensors[sensorId];
    // reset the name, if possible
    if (sensor.name == sensorId && flx != undefined && sensor.port != undefined) {
        sensor.name = flx[sensor.port].name + " " + sensor.subtype;
    }
    var value = JSON.parse(payload);
    // now compute the gauge
    switch (msgType) {
      case "gauge":
        // process currently only the FLM delivered values with timestamp
        if (value.length == 3 && value[2] === "W") {
            // check time difference of received value to current time
            // this is due to pulses being send on occurance, so potentially outdated
            var now = new Date().getTime();
            var diff = now / 1e3 - value[0];
            // drop values that are older than 10 sec - as this is a realtime view
            if (diff > 100) break;
            // check if current sensor was already registered
            var obj = series.filter(function(o) {
                return o.label == sensor.name;
            });
            if (obj[0] == null) {
                obj = series.filter(function(o) {
                    return o.label == sensor.id;
                });
            }
            // flot.time requires UTC-like timestamps;
            // see https://github.com/flot/flot/blob/master/API.md#time-series-data
            var timestamp = value[0] * 1e3;
            // ...if current sensor does not exist yet, register it
            if (obj[0] == null) {
                obj = {};
                obj.label = sensor.name;
                obj.data = [ timestamp, value[1] ];
                obj.color = color;
                color++;
                series.push(obj);
                // add graph select option
                $("#choices").append("
" + "" + "<input type='checkbox' id='" + sensor.name + "' checked='checked'></input>" + sensor.name + "" + "
");
            } else {
                // switch label from id to actual name (config came late)
                if (obj[0].label == sensor.id) {
                    obj[0].label = sensor.name;
                    $("#" + sensor.id).prop("id", sensor.name).parent().get(0).val(sensor.name);
                }
                obj[0].data.push([ timestamp, value[1] ]);
                // move out values older than 5 minutes
                var limit = parseInt(obj[0].data[0]);
                diff = (timestamp - limit) / 1e3;
                if (diff > 300) {
                    var selGraph = new Array();
                    for (var i in series) {
                        var selObj = {};
                        selObj.label = series[i].label;
                        selObj.data = series[i].data.filter(function(v) {
                            return v[0] > limit;
                        });
                        selObj.color = series[i].color;
                        selGraph.push(selObj);
                    }
                    series = selGraph;
                }
            }
        }
        // if length
        break;

      default:
        break;
    }
    // check the selected checkboxes
    selSeries = [];
    $("#choices").find("input:checked").each(function() {
        var key = $(this).attr("id");
        var s = series.filter(function(o) {
            return o.label == key;
        });
        selSeries.push(s[0]);
    });
    // plot the selection
    var width = $("#graphpanel").width();
    var height = width * 3 / 4;
    height = height > 600 ? 600 : height;
    $("#graph").width(width).height(height);
    $.plot("#graph", selSeries, options);
    // and store the sensor configuration
    sensors[sensorId] = sensor;
}<commit_msg>don't be overwhelmed by sensor data<commit_after>// state of showing the information panel
var infoVis = true;

$(function() {
    // allow tooltip on datapoints
    $("

").css({
        position: "absolute",
        display: "none",
        border: "1px solid #ccc",
        padding: "2px",
        opacity: .9
    }).appendTo("body");
    // assign hover function
    $("#graph").on("plothover", function(event, pos, item) {
        if (item) {
            var itemTime = new Date(item.datapoint[0]);
            var hrs = itemTime.getHours();
            hrs = hrs < 10 ? "0" + hrs : hrs;
            var min = itemTime.getMinutes();
            min = min < 10 ? "0" + min : min;
            var sec = itemTime.getSeconds();
            sec = sec < 10 ? "0" + sec : sec;
            $("#tooltip").html(hrs + ":" + min + ":" + sec + " : " + item.datapoint[1]).css({
                top: item.pageY + 7,
                left: item.pageX + 5
            }).fadeIn(200);
        } else $("#tooltip").hide();
    });
    // toggle the selection
    $("#toggle").click(function() {
        if (infoVis) $("#infopanel").hide(); else $("#infopanel").show();
        infoVis = !infoVis;
    });
});

// link to the web server's IP address for socket connection
var socket = io.connect(location.host);

// the received values
var series = new Array(), sensors = {};

// the selected series to show
var selSeries = new Array();

var color = 0;

var options = {
    series: {
        lines: {
            show: true,
            steps: true
        },
        points: {
            show: false
        }
    },
    grid: {
        hoverable: true
    },
    xaxis: {
        mode: "time",
        timezone: "browser"
    },
    yaxis: {
        min: 0
    }
};

// process socket connection
socket.on("connect", function() {
    var flx;
    socket.on("mqtt", function(msg) {
        // determine topic and payload
        var topic = msg.topic.split("/");
        var payload = msg.payload;
        switch (topic[1]) {
          case "device":
            handle_device(topic, payload);
            break;

          case "sensor":
            handle_sensor(flx, topic, payload);
            break;

          default:
            break;
        }
    });
    // handle the device information
    function handle_device(topic, payload) {
        var deviceID = topic[2];
        if (topic[4] == "flx") flx = JSON.parse(payload);
        if (topic[4] == "sensor") {
            var config = JSON.parse(payload);
            for (var obj in config) {
                var cfg = config[obj];
                if (cfg.enable == "1") {
                    if (sensors[cfg.id] == null) {
                        sensors[cfg.id] = new Object();
                        sensors[cfg.id].id = cfg.id;
                        if (cfg.function != undefined) {
                            sensors[cfg.id].name = cfg.function;
                        } else {
                            sensors[cfg.id].name = cfg.id;
                        }
                        if (cfg.subtype != undefined) sensors[cfg.id].subtype = cfg.subtype;
                        if (cfg.port != undefined) sensors[cfg.id].port = cfg.port[0];
                    } else {
                        if (cfg.function != undefined) sensors[cfg.id].name = cfg.function;
                    }
                }
            }
        }
    }
    socket.emit("subscribe", {
        topic: "/device/+/config/sensor"
    });
    socket.emit("subscribe", {
        topic: "/device/+/config/flx"
    });
    socket.emit("subscribe", {
        topic: "/sensor/+/gauge"
    });
});

// handle the sensor information
function handle_sensor(flx, topic, payload) {
    var sensor = {};
    var msgType = topic[3];
    var sensorId = topic[2];
    if (sensors[sensorId] == null) {
        sensors[sensorId] = new Object();
        sensor.id = sensorId;
        sensor.name = sensorId;
    } else sensor = sensors[sensorId];
    // reset the name, if possible
    if (sensor.name == sensorId && flx != undefined && sensor.port != undefined) {
        sensor.name = flx[sensor.port].name + " " + sensor.subtype;
    }
    var value = JSON.parse(payload);
    if (value.length != 3) return;
    if (value[2] !== "W") return;
    // now compute the gauge
    switch (msgType) {
      case "gauge":
        // process currently only the FLM delivered values with timestamp
        // check time difference of received value to current time
        // this is due to pulses being send on occurance, so potentially outdated
        var now = new Date().getTime();
        var diff = now / 1e3 - value[0];
        // drop values that are older than 10 sec - as this is a realtime view
        if (diff > 100) break;
        // check if current sensor was already registered
        var obj = series.filter(function(o) {
            return o.label == sensor.name;
        });
        if (obj[0] == null) {
            obj = series.filter(function(o) {
                return o.label == sensor.id;
            });
        }
        // flot.time requires UTC-like timestamps;
        // see https://github.com/flot/flot/blob/master/API.md#time-series-data
        var timestamp = value[0] * 1e3;
        // ...if current sensor does not exist yet, register it
        if (obj[0] == null) {
            obj = {};
            obj.label = sensor.name;
            obj.data = [ timestamp, value[1] ];
            obj.color = color;
            color++;
            series.push(obj);
            // add graph select option
            $("#choices").append("
" + "" + "<input type='checkbox' id='" + sensor.name + "' checked='checked'></input>" + sensor.name + "" + "
");
        } else {
            // switch label from id to actual name (config came late)
            if (obj[0].label == sensor.id) {
                obj[0].label = sensor.name;
                $("#" + sensor.id).prop("id", sensor.name).parent().get(0).val(sensor.name);
            }
            obj[0].data.push([ timestamp, value[1] ]);
            // move out values older than 5 minutes
            var limit = parseInt(obj[0].data[0]);
            diff = (timestamp - limit) / 1e3;
            if (diff > 300) {
                var selGraph = new Array();
                for (var i in series) {
                    var selObj = {};
                    selObj.label = series[i].label;
                    selObj.data = series[i].data.filter(function(v) {
                        return v[0] > limit;
                    });
                    selObj.color = series[i].color;
                    selGraph.push(selObj);
                }
                series = selGraph;
            }
        }
        break;

      default:
        break;
    }
    // check the selected checkboxes
    selSeries = [];
    $("#choices").find("input:checked").each(function() {
        var key = $(this).attr("id");
        var s = series.filter(function(o) {
            return o.label == key;
        });
        selSeries.push(s[0]);
    });
    // plot the selection
    var width = $("#graphpanel").width();
    var height = width * 3 / 4;
    height = height > 600 ? 600 : height;
    $("#graph").width(width).height(height);
    $.plot("#graph", selSeries, options);
    // and store the sensor configuration
    sensors[sensorId] = sensor;
}<|endoftext|>


<commit_before>const { parse } = require('url');
const { Argument } = require('klasa');

module.exports = class extends Argument {

	constructor(...args) {
		super(...args, { aliases: ['url'] });
	}

	run(arg, possible, msg) {
		const res = parse(arg);
		const hyperlink = res.protocol && res.hostname ? hyperlink : null;
		if (hyperlink !== null) return hyperlink;
		throw (msg.language || this.client.languages.default).get('RESOLVER_INVALID_URL', possible.name);
	}

};
<commit_msg>fix url argType<commit_after>const { parse } = require('url');
const { Argument } = require('klasa');

module.exports = class extends Argument {

	constructor(...args) {
		super(...args, { aliases: ['url'] });
	}

	run(arg, possible, msg) {
		const res = parse(arg);
		const hyperlink = res.protocol && res.hostname ? arg : null;
		if (hyperlink !== null) return hyperlink;
		throw (msg.language || this.client.languages.default).get('RESOLVER_INVALID_URL', possible.name);
	}

};
<|endoftext|>


<commit_before>/* global history */

import './common'

let Awesomplete = require('awesomplete') // eslint-disable-line
let geolib = require('geolib')
import List from 'list.js'
import Holder from 'holderjs'
import Find from 'lodash/collection/find'
import ForEach from 'lodash/collection/forEach'
import moment from 'moment'
import htmlEncode from 'htmlencode'
var ko = require('knockout')

let ContactFormModel = require('./models/GiveItemModel')
let apiRoutes = require('./api')
let browser = require('./browser')
let getApiData = require('./get-api-data')

let getLocation = require('./location/get-location')
let templating = require('./template-render')
let getUrlParams = require('./get-url-parameter')
let locationSelector = require('./location/locationSelector')
let socialShare = require('./social-share')
import listToSelect from './list-to-dropdown'

const activeClass = 'is-active'

let currentLocation = null

let onChangeLocation = (newLocation) => {
  window.location.href = '/give-help/help/?location=' + newLocation
}

let formatDate = (needs) => {
  ForEach(needs, function (need) {
    need.formattedCreationDate = moment(need.creationDate).fromNow()
  })

  return needs
}

let renderNeeds = (needs) => {
  let theData = {
    card: needs,
    location: currentLocation.name
  }

  if (needs.length === 0) {
    templating.renderTemplate('js-no-data-tpl', theData, 'js-card-list-output', () => {
      locationSelector.handler(onChangeLocation)
      browser.loaded()
    })
  } else {
    templating.renderTemplate('js-card-list-tpl', theData, 'js-card-list-output', () => {
      buildList()
      buildCard(needs)
      listToSelect.init()
      locationSelector.handler(onChangeLocation)
      initAutoComplete(needs)
      browser.loaded()
    })
  }
}

let initAutoComplete = (needs) => {
  let keywords = needs
    .map((n) => n.keywords)
    .filter((k) => k.length > 0)
    .join(',')

  let input = document.querySelector('.search')
  let awesomplete = new Awesomplete(input, {list: keywords}) // eslint-disable-line
}

let useDistanceForLocation = (position, needs) => {
  let latitude = position.coords.latitude
  let longitude = position.coords.longitude
  needs.forEach((n) => {
    let distanceInMetres = geolib.getDistance(
      { latitude: latitude, longitude: longitude },
      { latitude: n.latitude, longitude: n.longitude }
    )
    n.distanceAwayInMetres = distanceInMetres
    n.locationDescription = (distanceInMetres * 0.00062137).toFixed(2) + ' miles away'
  })

  return needs
}

let usePostcodeForLocation = (needs) => {
  needs.forEach((n) => {
    n.locationDescription = n.postcode
  })
  return needs
}

let init = () => {
  if (window.location.search.length === 0) {
    var saved = document.cookie.replace(/(?:(?:^|.*;\s*)desired-location\s*\=\s*([^;]*).*$)|^.*$/, '$1')
    if (saved !== undefined && saved.length > 0 && saved !== 'my-location') {
      onChangeLocation(saved)
    }
  }

  let location = getUrlParams.parameter('location')

  let url = apiRoutes.needs
  if (location.length > 0) {
    url = apiRoutes.serviceProviders + location + '/needs/'
  }
  getApiData.data(url)
    .then(function (result) {
      let needsFromApi = formatDate(result.data)

      if (navigator.geolocation) {
        getLocation.location().then(function (position) {
          renderNeeds(useDistanceForLocation(position, needsFromApi))
        }, () => {
          renderNeeds(usePostcodeForLocation(needsFromApi))
        })
      } else {
        renderNeeds(usePostcodeForLocation(needsFromApi))
      }
    })
}

let initList = () => {
   // List.js
  let options = {
    valueNames: [ 'type', 'serviceProviderName', 'creationDate', 'description', 'keywords', 'distanceAwayInMetres' ],
    plugins: []
  }

  let theList = new List('js-card-search', options)
  theList.sort('creationDate', { order: 'desc' })

  return theList
}

let initFiltering = (theList) => {
  let runFiltering = () => {
    if (activeFilters.length === 0) {
      resetFiltering()
      return
    }

    theList.filter((item) => {
      if (activeFilters.length > 0) {
        return (activeFilters.indexOf(item.values().type)) > -1
      }
      return true
    })
  }

  let resetFiltering = () => {
    // Reset active states
    let c
    let filters = document.querySelectorAll('.js-filter-item')

    activeFilters = []

    for (c = 0; c < filters.length; c++) {
      filters[c].classList.remove(activeClass)
    }

    document.querySelector('.js-filter-item-all').classList.add(activeClass)

    // Reset filter & layout
    theList.filter()
  }

  let filters = document.querySelectorAll('.js-filter-item')
  let activeFilters = []

  // Add click listener to each item
  for (let b = 0; b < filters.length; b++) {
    filters[b].addEventListener('click', (event) => {
      let self = event.target
      let getFilter = self.getAttribute('data-filter')
      event.preventDefault()

      if (getFilter === 'all') {
        resetFiltering()
      } else {
        document.querySelector('.js-filter-item-all').classList.remove(activeClass)
        ForEach(filters, (f) => f.classList.remove(activeClass))
        self.classList.add(activeClass)
        activeFilters = [getFilter]
        runFiltering()
      }
    })
  }

  // Add change listener to `<select>` for small screens
  let filterList = document.querySelectorAll('.js-filter-list.list-to-dropdown__select')
  for (let c = 0; c < filterList.length; c++) {
    filterList[c].addEventListener('change', () => {
    })
  }
}

let initSorting = (theList) => {
  const sortCriteriaButtons = document.querySelectorAll('.js-sort-criteria')
  ForEach(sortCriteriaButtons, (b) => {
    b.addEventListener('click', (event) => {
      let sortFields = []
      sortFields['organisation'] = 'serviceProviderName'
      sortFields['date'] = 'creationDate'
      sortFields['distance'] = 'distanceAwayInMetres'

      let selectedSort = event.target.getAttribute('data-sort')
      let [field, direction] = selectedSort.split('-')
      theList.sort(sortFields[field], { order: direction })

      ForEach(sortCriteriaButtons, (cb) => {
        cb.classList.remove(activeClass)
      })
      event.target.classList.add(activeClass)
    })
  })
}

let buildList = () => {
  let theList = initList()

  initFiltering(theList)
  initSorting(theList)
}

// Full detail view
let buildCard = (data) => {
  const searchSelector = '#js-card-search'
  const cardDetailSelector = '.js-card-detail'
  const hiddenClass = 'is-hidden'

  let updateMeta = (title, description) => {
    let newTitle = htmlEncode.htmlDecode(title)
    let newDescription = htmlEncode.htmlDecode(description)

    document.querySelector('meta[property="og:title"]').setAttribute('content', newTitle)
    document.querySelector('meta[property="og:description"]').setAttribute('content', newDescription)
    document.title = newTitle
    document.description = newDescription
  }

  let openCard = (el, callback) => {
    let cardCallback = () => {
      document.querySelector(cardDetailSelector).classList.remove(hiddenClass)
      document.querySelector(cardDetailSelector).classList.add(activeClass)

      window.scrollTo(0, 0)

      let theId = el.getAttribute('data-id')
      let cardData = Find(data, (c) => {
        return c.id === theId
      })

      let iCanHelpButton = document.querySelector('.js-i-can-help-button')
      iCanHelpButton.addEventListener('click', function (event) {
        event.preventDefault()
        if (cardData.type === 'money') {
          window.location = cardData.donationUrl
        } else {
          browser.scrollTo('.requests-detail__heading--i-can-help')
        }
      })

      let contactFormModel = new ContactFormModel()
      contactFormModel.needId = theId
      ko.applyBindings(contactFormModel, document.querySelector('.requests-detail__form'))

      initFbShare()

      Holder.run({})

      // TODO: Proper URL support
      let state = { test: 'TBA' }
      history.pushState(state, 'TEST', '?id=' + theId)

      ForEach(document.querySelectorAll('.js-card-back'), (link) => {
        link.addEventListener('click', (event) => {
          event.preventDefault()
          callback()
        })
      })

      socialShare.updateSharePageHrefs()
    }

    let initFbShare = () => {
      let el = document.querySelector('.js-fb-share-page')
      el.addEventListener('click', function (e) {
        e.preventDefault()
        var facebookAppID = '244120752609710'
        let url = 'https://www.facebook.com/dialog/feed?app_id=' + facebookAppID +
        '&link=' + encodeURIComponent(window.location.href) +
        '&name=' + encodeURIComponent(document.title) +
        '&description=' + encodeURIComponent(document.description) +
        '&redirect_uri=https://www.facebook.com'
        window.open(url)
      })
    }

    let initCardDetail = () => {
      let theId = el.getAttribute('data-id')
      let cardData = Find(data, (o) => { return o.id === theId })

      cardData.showLocation = cardData.postcode.length > 0 && cardData.type !== 'money'
      cardData.showContactForm = cardData.type !== 'money'

      updateMeta(cardData.description + ' needed for ' + cardData.serviceProviderName, cardData.reason)

      // hide search
      document.querySelector(searchSelector).classList.remove(activeClass)
      document.querySelector(searchSelector).classList.add(hiddenClass)

      // Append object name for Hogan
      let theCardTemplateData = { card: cardData }

      templating.renderTemplate('js-card-detail-tpl', theCardTemplateData, 'js-card-detail-output', cardCallback)
    }

    initCardDetail()
  }

  let openIfCardRequested = () => {
    let cardId = getUrlParams.parameter('id').replace('/', '')
    if (cardId) {
      let card = Find(document.querySelectorAll('.requests-listing__item'), (c) => {
        return c.getAttribute('data-id') === cardId
      })
      openCard(card, () => {
        history.pushState({}, 'from openIfCardRequested', '?')
        closeCard()
      })
    }
  }

  let rewindHistory = () => {
    window.history.back()
  }

  let closeCard = () => {
    document.querySelector(searchSelector).classList.remove(hiddenClass)
    document.querySelector(searchSelector).classList.add(activeClass)

    document.querySelector(cardDetailSelector).classList.remove(activeClass)
    document.querySelector(cardDetailSelector).classList.add(hiddenClass)

    updateMeta('Requests for Help - Street Support', 'Organisations need specific items, skills and money to support homeless people in Manchester - can you help?')
  }

  let addClickEvents = () => {
    let addEventListener = (card) => {
      card.addEventListener('click', function (event) {
        event.preventDefault()
        openCard(this, rewindHistory)
      })
    }
    ForEach(document.querySelectorAll('.requests-listing__item'), addEventListener)
  }

  window.onpopstate = () => {
    closeCard()
    openIfCardRequested()
  }

  addClickEvents()
  openIfCardRequested()
}

browser.loading()
locationSelector
  .getCurrent()
  .then((result) => {
    currentLocation = result
    init()
  }, (_) => {

  })
<commit_msg>lintin<commit_after>/* global history */

import './common'

let Awesomplete = require('awesomplete') // eslint-disable-line
let geolib = require('geolib')
import List from 'list.js'
import Holder from 'holderjs'
import Find from 'lodash/collection/find'
import ForEach from 'lodash/collection/forEach'
import moment from 'moment'
import htmlEncode from 'htmlencode'
var ko = require('knockout')

let ContactFormModel = require('./models/GiveItemModel')
let apiRoutes = require('./api')
let browser = require('./browser')
let getApiData = require('./get-api-data')

let getLocation = require('./location/get-location')
let templating = require('./template-render')
let getUrlParams = require('./get-url-parameter')
let locationSelector = require('./location/locationSelector')
let socialShare = require('./social-share')
import listToSelect from './list-to-dropdown'

const activeClass = 'is-active'

let currentLocation = null

let onChangeLocation = (newLocation) => {
  window.location.href = '/give-help/help/?location=' + newLocation
}

let formatDate = (needs) => {
  ForEach(needs, function (need) {
    need.formattedCreationDate = moment(need.creationDate).fromNow()
  })

  return needs
}

let renderNeeds = (needs) => {
  let theData = {
    card: needs,
    location: currentLocation.name
  }

  if (needs.length === 0) {
    templating.renderTemplate('js-no-data-tpl', theData, 'js-card-list-output', () => {
      locationSelector.handler(onChangeLocation)
      browser.loaded()
    })
  } else {
    templating.renderTemplate('js-card-list-tpl', theData, 'js-card-list-output', () => {
      buildList()
      buildCard(needs)
      listToSelect.init()
      locationSelector.handler(onChangeLocation)
      initAutoComplete(needs)
      browser.loaded()
    })
  }
}

let initAutoComplete = (needs) => {
  let keywords = needs
    .map((n) => n.keywords)
    .filter((k) => k.length > 0)
    .join(',')

  let input = document.querySelector('.search')
  let awesomplete = new Awesomplete(input, {list: keywords}) // eslint-disable-line
}

let useDistanceForLocation = (position, needs) => {
  let latitude = position.coords.latitude
  let longitude = position.coords.longitude
  needs.forEach((n) => {
    let distanceInMetres = geolib.getDistance(
      { latitude: latitude, longitude: longitude },
      { latitude: n.latitude, longitude: n.longitude }
    )
    n.distanceAwayInMetres = distanceInMetres
    n.locationDescription = (distanceInMetres * 0.00062137).toFixed(2) + ' miles away'
  })

  return needs
}

let usePostcodeForLocation = (needs) => {
  needs.forEach((n) => {
    n.locationDescription = n.postcode
  })
  return needs
}

let init = () => {
  if (window.location.search.length === 0) {
    var saved = document.cookie.replace(/(?:(?:^|.*;\s*)desired-location\s*\=\s*([^;]*).*$)|^.*$/, '$1')
    if (saved !== undefined && saved.length > 0 && saved !== 'my-location') {
      onChangeLocation(saved)
    }
  }

  let location = getUrlParams.parameter('location')

  let url = apiRoutes.needs
  if (location.length > 0) {
    url = apiRoutes.serviceProviders + location + '/needs/'
  }
  getApiData.data(url)
    .then(function (result) {
      let needsFromApi = formatDate(result.data)

      if (navigator.geolocation) {
        getLocation.location().then(function (position) {
          renderNeeds(useDistanceForLocation(position, needsFromApi))
        }, () => {
          renderNeeds(usePostcodeForLocation(needsFromApi))
        })
      } else {
        renderNeeds(usePostcodeForLocation(needsFromApi))
      }
    })
}

let initList = () => {
   // List.js
  let options = {
    valueNames: [ 'type', 'serviceProviderName', 'creationDate', 'description', 'keywords', 'distanceAwayInMetres' ],
    plugins: []
  }

  let theList = new List('js-card-search', options)
  theList.sort('creationDate', { order: 'desc' })

  return theList
}

let initFiltering = (theList) => {
  let runFiltering = () => {
    if (activeFilters.length === 0) {
      resetFiltering()
      return
    }

    theList.filter((item) => {
      if (activeFilters.length > 0) {
        return (activeFilters.indexOf(item.values().type)) > -1
      }
      return true
    })
  }

  let resetFiltering = () => {
    // Reset active states
    let c
    let filters = document.querySelectorAll('.js-filter-item')

    activeFilters = []

    for (c = 0; c < filters.length; c++) {
      filters[c].classList.remove(activeClass)
    }

    document.querySelector('.js-filter-item-all').classList.add(activeClass)

    // Reset filter & layout
    theList.filter()
  }

  let filters = document.querySelectorAll('.js-filter-item')
  let activeFilters = []

  // Add click listener to each item
  for (let b = 0; b < filters.length; b++) {
    filters[b].addEventListener('click', (event) => {
      let self = event.target
      let getFilter = self.getAttribute('data-filter')
      event.preventDefault()

      if (getFilter === 'all') {
        resetFiltering()
      } else {
        document.querySelector('.js-filter-item-all').classList.remove(activeClass)
        ForEach(filters, (f) => f.classList.remove(activeClass))
        self.classList.add(activeClass)
        activeFilters = [getFilter]
        runFiltering()
      }
    })
  }

  // Add change listener to `<select>` for small screens
  let filterList = document.querySelectorAll('.js-filter-list.list-to-dropdown__select')
  for (let c = 0; c < filterList.length; c++) {
    filterList[c].addEventListener('change', () => {
    })
  }
}

let initSorting = (theList) => {
  const sortCriteriaButtons = document.querySelectorAll('.js-sort-criteria')
  ForEach(sortCriteriaButtons, (b) => {
    b.addEventListener('click', (event) => {
      let sortFields = []
      sortFields['organisation'] = 'serviceProviderName'
      sortFields['date'] = 'creationDate'
      sortFields['distance'] = 'distanceAwayInMetres'

      let selectedSort = event.target.getAttribute('data-sort')
      let [field, direction] = selectedSort.split('-')
      theList.sort(sortFields[field], { order: direction })

      ForEach(sortCriteriaButtons, (cb) => {
        cb.classList.remove(activeClass)
      })
      event.target.classList.add(activeClass)
    })
  })
}

let buildList = () => {
  let theList = initList()

  initFiltering(theList)
  initSorting(theList)
}

// Full detail view
let buildCard = (data) => {
  const searchSelector = '#js-card-search'
  const cardDetailSelector = '.js-card-detail'
  const hiddenClass = 'is-hidden'

  let updateMeta = (title, description) => {
    let newTitle = htmlEncode.htmlDecode(title)
    let newDescription = htmlEncode.htmlDecode(description)

    document.querySelector('meta[property="og:title"]').setAttribute('content', newTitle)
    document.querySelector('meta[property="og:description"]').setAttribute('content', newDescription)
    document.title = newTitle
    document.description = newDescription
  }

  let openCard = (el, callback) => {
    let cardCallback = () => {
      document.querySelector(cardDetailSelector).classList.remove(hiddenClass)
      document.querySelector(cardDetailSelector).classList.add(activeClass)

      window.scrollTo(0, 0)

      let theId = el.getAttribute('data-id')
      let cardData = Find(data, (c) => {
        return c.id === theId
      })

      let iCanHelpButton = document.querySelector('.js-i-can-help-button')
      iCanHelpButton.addEventListener('click', function (event) {
        event.preventDefault()
        if (cardData.type === 'money') {
          window.location = cardData.donationUrl
        } else {
          browser.scrollTo('.requests-detail__heading--i-can-help')
        }
      })

      let contactFormModel = new ContactFormModel()
      contactFormModel.needId = theId
      ko.applyBindings(contactFormModel, document.querySelector('.requests-detail__form'))

      initFbShare()

      Holder.run({})

      // TODO: Proper URL support
      let state = { test: 'TBA' }
      history.pushState(state, 'TEST', '?id=' + theId)

      ForEach(document.querySelectorAll('.js-card-back'), (link) => {
        link.addEventListener('click', (event) => {
          event.preventDefault()
          callback()
        })
      })

      socialShare.updateSharePageHrefs()
    }

    let initFbShare = () => {
      let el = document.querySelector('.js-fb-share-page')
      el.addEventListener('click', function (e) {
        e.preventDefault()
        var facebookAppID = '244120752609710'
        let url = 'https://www.facebook.com/dialog/feed?app_id=' + facebookAppID +
        '&link=' + encodeURIComponent(window.location.href) +
        '&name=' + encodeURIComponent(document.title) +
        '&description=' + encodeURIComponent(document.description) +
        '&redirect_uri=https://www.facebook.com'
        window.open(url)
      })
    }

    let initCardDetail = () => {
      let theId = el.getAttribute('data-id')
      let cardData = Find(data, (o) => { return o.id === theId })

      cardData.showLocation = cardData.postcode.length > 0 && cardData.type !== 'money'
      cardData.showContactForm = cardData.type !== 'money'

      updateMeta(cardData.description + ' needed for ' + cardData.serviceProviderName, cardData.reason)

      // hide search
      document.querySelector(searchSelector).classList.remove(activeClass)
      document.querySelector(searchSelector).classList.add(hiddenClass)

      // Append object name for Hogan
      let theCardTemplateData = { card: cardData }

      templating.renderTemplate('js-card-detail-tpl', theCardTemplateData, 'js-card-detail-output', cardCallback)
    }

    initCardDetail()
  }

  let openIfCardRequested = () => {
    let cardId = getUrlParams.parameter('id').replace('/', '')
    if (cardId) {
      let card = Find(document.querySelectorAll('.requests-listing__item'), (c) => {
        return c.getAttribute('data-id') === cardId
      })
      openCard(card, () => {
        history.pushState({}, 'from openIfCardRequested', '?')
        closeCard()
      })
    }
  }

  let rewindHistory = () => {
    window.history.back()
  }

  let closeCard = () => {
    document.querySelector(searchSelector).classList.remove(hiddenClass)
    document.querySelector(searchSelector).classList.add(activeClass)

    document.querySelector(cardDetailSelector).classList.remove(activeClass)
    document.querySelector(cardDetailSelector).classList.add(hiddenClass)

    updateMeta('Requests for Help - Street Support', 'Organisations need specific items, skills and money to support homeless people in Manchester - can you help?')
  }

  let addClickEvents = () => {
    let addEventListener = (card) => {
      card.addEventListener('click', function (event) {
        event.preventDefault()
        openCard(this, rewindHistory)
      })
    }
    ForEach(document.querySelectorAll('.requests-listing__item'), addEventListener)
  }

  window.onpopstate = () => {
    closeCard()
    openIfCardRequested()
  }

  addClickEvents()
  openIfCardRequested()
}

browser.loading()
locationSelector
  .getCurrent()
  .then((result) => {
    currentLocation = result
    init()
  }, (_) => {

  })
<|endoftext|>


<commit_before>"use strict";
const { Event } = require("sosamba");
const { version: sosambaVersion } = require("sosamba/package.json");
const { version } = require("../package.json");

class CommandErrorEvent extends Event {
    constructor(...args) {
        super(...args, {
            name: "commandError"
        });
    }

    async run(e, ctx) {
        if (e.constructor.name !== "ExtensionError") this.log.error(e);
        try {
            await ctx.send({
                embed: {
                    title: ":x: Error running the command",
                    description: `I am unable to run the command because of a coding error:\n\`\`\`js\n${e.stack}\n\`\`\``,
                    color: 0xFF0000,
                    footer: {
                        text: `Please tell the command developers about this. | tt.bot v${version} running on Sosamba v${sosambaVersion}`
                    }
                }
            });
        } catch {}
    }
}

module.exports = CommandErrorEvent;<commit_msg>Change a bit of text<commit_after>"use strict";
const { Event } = require("sosamba");
const { version: sosambaVersion } = require("sosamba/package.json");
const { version } = require("../package.json");

class CommandErrorEvent extends Event {
    constructor(...args) {
        super(...args, {
            name: "commandError"
        });
    }

    async run(e, ctx) {
        if (e.constructor.name !== "ExtensionError") this.log.error(e);
        try {
            await ctx.send({
                embed: {
                    title: ":x: Error running the command",
                    description: `I am unable to run the command because of a coding error:\n\`\`\`js\n${e.stack}\n\`\`\``,
                    color: 0xFF0000,
                    footer: {
                        text: `Please report this issue on our support server or on GitHub. | tt.bot v${version} running on Sosamba v${sosambaVersion}`
                    }
                }
            });
        } catch {}
    }
}

module.exports = CommandErrorEvent;<|endoftext|>


<commit_before>"use strict";

var application = new Base();

function Base () {
    this.requestAjax = function (action, params, callbacks) {
        return new BaseRequestAjax(action, params, callbacks);
    };

    this.modal = function (title, content, footer) {
        return new BaseModal(title, content, footer);
    };

    this.errorForm = function (errors, formId)
    {
        if (typeof errors !== 'object') {
            return this;
        }
        formId = undefined == formId ? '' : '#' + formId + ' ';

        $.each(errors, function (index, value) {
            var listError = '';

            $.each(value, function (key, message) {
                listError += '' + message + '';
            });

            $(formId + '#' + index).parents('.form-group')
                .addClass('has-error')
                .append('
' + listError + '
');
        })
    };
}

function BaseRequestAjax (action, params, callbacks)
{
    var self = this,
        optionsAjax = {
            url: '',
            data: '',
            method: 'GET',
            success: function (data, textStatus, jqXHR) {},
            beforeSend: function (jqXHR, settings) {},
            complete: function (jqXHR, textStatus) {},
            error: function (jqXHR, textStatus, errorThrown) {}
        },
        initOptionsAjax = function () {
            optionsAjax.url = self.action;
            optionsAjax.method = self.method;
            optionsAjax.data = self.params;

            if (typeof self.callbacks == 'object') {
                $.each(self.callbacks, function (index, value) {
                    if (typeof value == 'function') {
                        optionsAjax[index] = value;
                    }
                });
            }
        };

    this.action = action;

    this.method = 'GET';

    this.params = params;

    this.callbacks = callbacks;

    this.send = function (method, options)
    {
        this.method = undefined === method ? this.method : method;
        initOptionsAjax();
        this.setOptions(options);

        $.ajax(optionsAjax);

        return this;
    };

    this.setOptions = function (options) {
        if (undefined === options) {
            return this;
        }

        $.each(options, function (index, value) {
            optionsAjax[index] = value;
        });

        return this;
    };
}

function BaseModal (title, content, footer)
{
    var self = this,
        _id = '#modal-default',
        _title = title,
        _content = content,
        _footer = footer,
        _setModal = function () {
            var $modal = $(_id);
            $modal.find('#modal-title').html(_title);
            $modal.find('.modal-body').html(_content);
            $modal.find('.modal-footer').html(_footer);
        };

    this.open = function () {
        _setModal();
        $(_id).modal();
        return this;
    };

    this.close = function () {
        $(_id + ' .modal-header button').trigger('click');
        return this;
    };

    this.id = function (id) {
        if (undefined == id) {
            return _id;
        }

        _id = id;
        return this;
    };

    this.title = function (title) {
        if (undefined == title) {
            return _title;
        }

        _title = title;
        return this;
    };

    this.content = function (content) {
        if (undefined == content) {
            return _content;
        }

        _content = content;
        return this;
    };

    this.footer = function (footer) {
        if (undefined == footer) {
            return _footer;
        }

        _footer = footer;
        return this;
    };
}

function BaseEvents()
{
    var _responseSuccess = function ($this, response) {
            toastr.success(
                response.message == undefined ? 'Ação realizada.' : response.message,
                'Sucesso!'
            );

            if ($this.attr('data-target')) {
                $($this.attr('data-target')).trigger('click');
            }

            if ($this.hasClass('close-modal')) {
                application.modal().close();
            }

            return true;
        },
        _responseError = function ($this, response) {
            toastr.warning(
                response.message == undefined
                    ? 'Não consegui concluir a ação, por favor tente novamente.'
                    : response.message,
                'Ação não realizada!'
            );

            return false;
        };

    this.submitAjax = (function () {
        var $this,
            ajaxCallbacks = {
                success: function (response) {
                    if (response === true || (response.status !== undefined && response.status)) {
                        return _responseSuccess($this, response)
                    }

                    return _responseError($this, response);
                },
                error: function (jqXHR) {
                    application.errorForm(jqXHR.responseJSON)
                }
            },
            onSubmit = function (event) {
                event.preventDefault();
                $this = $(this);
                application
                    .requestAjax(
                        $this.attr('action'),
                        $this.serialize()
                    )
                    .send($this.attr('method'), ajaxCallbacks)
            };

        $('body').on('submit', '.submit.ajax', onSubmit);

    })();

    this.ajax = (function () {
        var $this,
            ajaxCallbacks = {
                success: function (response) {
                    if (response === true || (response.status !== undefined && response.status == true)) {
                        return _responseSuccess($this, response)
                    }

                    return _responseError($this, response);
                }
            },
            onClick = function (event) {
                event.preventDefault();
                $this = $(this);
                application.requestAjax($this.attr('href'))
                    .send('GET', ajaxCallbacks);
            };

        $('body').on('click', '.click.ajax', onClick);

    })();

    this.modal = (function () {
        var modal = application.modal(),
            $this,
            title,
            ajaxCallbacks = {
                success: function (response) {
                    modal.content(response)
                        .open();
                },
                error: function (response) {
                    if (response.status == 401) {
                        modal.content(response.responseText)
                            .open();
                    }
                }
            },
            onClick = function (event) {
                event.preventDefault();
                $this = $(this);

                if ((title = $this.attr('title')) || (title = $this.attr('data-title'))) {
                    modal.title(title);
                }

                application.requestAjax($this.attr('href'))
                    .send('GET', ajaxCallbacks);
            };

        $('body').on('click', '.click-modal', onClick);
    })();

    this.clickTabs = (function () {
        var $this,
            callbacks = {
                success: function (response) {
                    $($this.attr('href')).html(response);
                },
                error: function (response) {
                    if (response.status == 401) {
                        $($this.attr('href'))
                            .html('

' + response.responseText + '

');
                    }
                }
            },
            navClick = function () {
                $this = $(this);

                if (undefined === $this.data('href')) {
                    return true;
                }

                application
                    .requestAjax($this.data('href'), [], callbacks)
                    .send();
            };

        $('body').on('click', '.nav li a', navClick);
    })();

    this.autocompleteButton = (function () {
        var $this,
            onClick = function () {
                $this = $(this);

                if ($this.find('.btn-default').hasClass('disabled')) {
                    return false;
                }

                $this
                    .parents('.typeahead__field')
                    .find('.typeahead')
                    .trigger('input.typeahead')
                    .trigger('focus.typeahead');
            };

        $('body').on('click', '.typeahead__button', onClick);
    })();
}

$(document).ready(function () {
    new BaseEvents();
});

$.ajaxSetup({
    headers: {
        'X-CSRF-Token': $('input[name="_token"]').val()
    }
});<commit_msg>adicionando script para selecionar checkbox (iCheck)<commit_after>"use strict";

var application = new Base();

function Base () {
    this.requestAjax = function (action, params, callbacks) {
        return new BaseRequestAjax(action, params, callbacks);
    };

    this.modal = function (title, content, footer) {
        return new BaseModal(title, content, footer);
    };

    this.errorForm = function (errors, formId)
    {
        if (typeof errors !== 'object') {
            return this;
        }
        formId = undefined == formId ? '' : '#' + formId + ' ';

        $.each(errors, function (index, value) {
            var listError = '';

            $.each(value, function (key, message) {
                listError += '' + message + '';
            });

            $(formId + '#' + index).parents('.form-group')
                .addClass('has-error')
                .append('
' + listError + '
');
        })
    };
}

function BaseRequestAjax (action, params, callbacks)
{
    var self = this,
        optionsAjax = {
            url: '',
            data: '',
            method: 'GET',
            success: function (data, textStatus, jqXHR) {},
            beforeSend: function (jqXHR, settings) {},
            complete: function (jqXHR, textStatus) {},
            error: function (jqXHR, textStatus, errorThrown) {}
        },
        initOptionsAjax = function () {
            optionsAjax.url = self.action;
            optionsAjax.method = self.method;
            optionsAjax.data = self.params;

            if (typeof self.callbacks == 'object') {
                $.each(self.callbacks, function (index, value) {
                    if (typeof value == 'function') {
                        optionsAjax[index] = value;
                    }
                });
            }
        };

    this.action = action;

    this.method = 'GET';

    this.params = params;

    this.callbacks = callbacks;

    this.send = function (method, options)
    {
        this.method = undefined === method ? this.method : method;
        initOptionsAjax();
        this.setOptions(options);

        $.ajax(optionsAjax);

        return this;
    };

    this.setOptions = function (options) {
        if (undefined === options) {
            return this;
        }

        $.each(options, function (index, value) {
            optionsAjax[index] = value;
        });

        return this;
    };
}

function BaseModal (title, content, footer)
{
    var self = this,
        _id = '#modal-default',
        _title = title,
        _content = content,
        _footer = footer,
        _setModal = function () {
            var $modal = $(_id);
            $modal.find('#modal-title').html(_title);
            $modal.find('.modal-body').html(_content);
            $modal.find('.modal-footer').html(_footer);
        };

    this.open = function () {
        _setModal();
        $(_id).modal();
        return this;
    };

    this.close = function () {
        $(_id + ' .modal-header button').trigger('click');
        return this;
    };

    this.id = function (id) {
        if (undefined == id) {
            return _id;
        }

        _id = id;
        return this;
    };

    this.title = function (title) {
        if (undefined == title) {
            return _title;
        }

        _title = title;
        return this;
    };

    this.content = function (content) {
        if (undefined == content) {
            return _content;
        }

        _content = content;
        return this;
    };

    this.footer = function (footer) {
        if (undefined == footer) {
            return _footer;
        }

        _footer = footer;
        return this;
    };
}

function BaseEvents()
{
    var _responseSuccess = function ($this, response) {
            toastr.success(
                response.message == undefined ? 'Ação realizada.' : response.message,
                'Sucesso!'
            );

            if ($this.attr('data-target')) {
                $($this.attr('data-target')).trigger('click');
            }

            if ($this.hasClass('close-modal')) {
                application.modal().close();
            }

            return true;
        },
        _responseError = function ($this, response) {
            toastr.warning(
                response.message == undefined
                    ? 'Não consegui concluir a ação, por favor tente novamente.'
                    : response.message,
                'Ação não realizada!'
            );

            return false;
        };

    this.submitAjax = (function () {
        var $this,
            ajaxCallbacks = {
                success: function (response) {
                    if (response === true || (response.status !== undefined && response.status)) {
                        return _responseSuccess($this, response)
                    }

                    return _responseError($this, response);
                },
                error: function (jqXHR) {
                    application.errorForm(jqXHR.responseJSON)
                }
            },
            onSubmit = function (event) {
                event.preventDefault();
                $this = $(this);
                application
                    .requestAjax(
                        $this.attr('action'),
                        $this.serialize()
                    )
                    .send($this.attr('method'), ajaxCallbacks)
            };

        $('body').on('submit', '.submit.ajax', onSubmit);

    })();

    this.ajax = (function () {
        var $this,
            ajaxCallbacks = {
                success: function (response) {
                    if (response === true || (response.status !== undefined && response.status == true)) {
                        return _responseSuccess($this, response)
                    }

                    return _responseError($this, response);
                }
            },
            onClick = function (event) {
                event.preventDefault();
                $this = $(this);
                application.requestAjax($this.attr('href'))
                    .send('GET', ajaxCallbacks);
            };

        $('body').on('click', '.click.ajax', onClick);

    })();

    this.modal = (function () {
        var modal = application.modal(),
            $this,
            title,
            ajaxCallbacks = {
                success: function (response) {
                    modal.content(response)
                        .open();
                },
                error: function (response) {
                    if (response.status == 401) {
                        modal.content(response.responseText)
                            .open();
                    }
                }
            },
            onClick = function (event) {
                event.preventDefault();
                $this = $(this);

                if ((title = $this.attr('title')) || (title = $this.attr('data-title'))) {
                    modal.title(title);
                }

                application.requestAjax($this.attr('href'))
                    .send('GET', ajaxCallbacks);
            };

        $('body').on('click', '.click-modal', onClick);
    })();

    this.clickTabs = (function () {
        var $this,
            callbacks = {
                success: function (response) {
                    $($this.attr('href')).html(response);
                },
                error: function (response) {
                    if (response.status == 401) {
                        $($this.attr('href'))
                            .html('

' + response.responseText + '

');
                    }
                }
            },
            navClick = function () {
                $this = $(this);

                if (undefined === $this.data('href')) {
                    return true;
                }

                application
                    .requestAjax($this.data('href'), [], callbacks)
                    .send();
            };

        $('body').on('click', '.nav li a', navClick);
    })();

    this.autocompleteButton = (function () {
        var $this,
            onClick = function () {
                $this = $(this);

                if ($this.find('.btn-default').hasClass('disabled')) {
                    return false;
                }

                $this
                    .parents('.typeahead__field')
                    .find('.typeahead')
                    .trigger('input.typeahead')
                    .trigger('focus.typeahead');
            };

        $('body').on('click', '.typeahead__button', onClick);
    })();

    this.checkAll = function () {
        var $this,
            $list,
            onClick = function () {
                $this = $(this);
                $list = $this.parents('table');

                if(!this.changed) {
                    this.changed = true;
                    $list.iCheck('check');
                    return true;
                }

                this.changed = false;
                $list.iCheck('uncheck');
            };

        $('body').on('ifChanged', '.check-all', onClick);
    }();
}

BaseEvents.iCheckPlugin = function (color) {
    color = color == undefined ? 'grey' : color;

    var iCheck = function () {
        $('input').iCheck({
            checkboxClass: 'icheckbox_square-' + color,
            radioClass: 'iradio_square-' + color,
            increaseArea: '20%'
        });
    };

    $(document)
        .ready(iCheck)
        .ajaxSuccess(iCheck);
};

$(document).ready(function () {
    new BaseEvents();
});

$.ajaxSetup({
    headers: {
        'X-CSRF-Token': $('input[name="_token"]').val()
    }
});<|endoftext|>


<commit_before>// Common modules
import './common'

// Page modules
var awesomplete = require('imports?this=>window!../../node_modules/awesomplete/awesomplete.js') // eslint-disable-line
import List from 'list.js'
// var ListFuzzySearch = require('imports?this=>window!../../node_modules/list.fuzzysearch.js/dist/list.fuzzysearch.js')
import Holder from 'holderjs'
import Bricks from 'bricks.js'

// Page modules
var apiRoutes = require('./api')
var getApiData = require('./get-api-data')
var templating = require('./template-render')
// var Spinner = require('spin.js')

import Find from 'lodash/collection/find'

// Spinner
// var spin = document.getElementById('spin')
// var loading = new Spinner().spin(spin)

// Run Holder
Holder.run({})

// Get API data using promise
getApiData.data(apiRoutes.needs)
  .then(function (result) {
    var needsFromApi = result.data
    // var theData = { 'needs': needsFromApi }

    console.log(needsFromApi)

    // List.js
    var options = {
      valueNames: [ 'id', 'type', 'serviceProviderId', 'description' ],
      item: '

',
      plugins: [
        // ListFuzzySearch()
      ]
    }

    const theList = new List('js-card-search', options, needsFromApi)

    // Bricks.js
    const sizes = [
      { columns: 1, gutter: 20 }, // assumed to be mobile, because of the missing mq property
      { mq: '360px', columns: 1, gutter: 20 },
      { mq: '480px', columns: 2, gutter: 20 },
      { mq: '600px', columns: 2, gutter: 20 },
      { mq: '800px', columns: 3, gutter: 20 }
    ]

    const cardLayout = Bricks({
      container: '.list',
      packed: 'data-packed', // if not prefixed with 'data-', it will be added
      sizes: sizes
    })

    cardLayout
      .resize(true) // bind resize handler
      .pack() // pack initial items

    // List.js Triggers
    theList.on('sortStart', () =>
      cardLayout.pack()
    )

    theList.on('searchComplete', () =>
      cardLayout.pack()
    )

    // Filtering
    var b
    var filters = document.querySelectorAll('.js-filter-item')
    var activeFilters = []

    // Add click listener to each item
    for (b = 0; b < filters.length; b++) {
      filters[b].addEventListener('click', function (event) {
        var getFilter = this.getAttribute('data-filter')
        event.preventDefault()

        console.log('filter clicked: ' + getFilter)

        if (getFilter === 'all') {
          activeFilters = []
          resetFiltering()
        } else {
          if (this.classList.contains('is-active')) {
            console.log('already active')
            this.classList.remove('is-active')
            activeFilters.splice(activeFilters.indexOf(getFilter), 1)
            runFiltering()
          } else {
            console.log('not active')

            document.querySelector('.js-filter-item-all').classList.remove('is-active')
            this.classList.add('is-active')
            activeFilters.push(getFilter)
            runFiltering()
          }
        }
      })
    }

    var runFiltering = function () {
      console.log('active filters: ' + activeFilters)

      theList.filter(function (item) {
        if (activeFilters.length > 0) {
          return (activeFilters.indexOf(item.values().type)) > -1
        }
        return true
      })

      cardLayout.pack()
    }

    var resetFiltering = function () {
      // Reset active states
      var c
      var filters = document.querySelectorAll('.js-filter-item')

      console.log('active filters: ' + activeFilters)

      for (c = 0; c < filters.length; c++) {
        filters[c].classList.remove('is-active')
      }

      document.querySelector('.js-filter-item-all').classList.add('is-active')

      // Reset filter & layout
      theList.filter()
      cardLayout.pack()
    }

    // Full detail view
    var a
    var items = document.querySelectorAll('.list li')

    // Add click listener to each item
    for (a = 0; a < items.length; a++) {
      items[a].addEventListener('click', function (event) {
        event.preventDefault()
        openCard(this)
      })
    }

    var openCard = function (el) {
      var theId = el.getElementsByClassName('id')[0].textContent
      var cardData = Find(needsFromApi, function (o) { return o.id === theId })

      // hide search
      document.querySelector('#js-card-search').classList.remove('is-active')
      document.querySelector('#js-card-search').classList.add('is-hidden')

      // Append object name for Hogan
      var theTemplateData = { card: cardData }

      var callback = function () {
        document.querySelector('.js-card-detail').classList.remove('is-hidden')
        document.querySelector('.js-card-detail').classList.add('is-active')

        window.scrollTo(0, 0)
      }

      templating.renderTemplate('js-card-detail-tpl', theTemplateData, 'js-card-detail-output', callback)
    }
  })

// Example bricks.js api
/*
cardSort
  .on('pack', () => console.log('ALL grid items packed.'))
  .on('update', () => console.log('NEW grid items packed.'))
  .on('resize', size => console.log('The grid has be re-packed to accommodate a new BREAKPOINT.'))
*/
<commit_msg>if every filter is deselected, reset back to all<commit_after>// Common modules
import './common'

// Page modules
var awesomplete = require('imports?this=>window!../../node_modules/awesomplete/awesomplete.js') // eslint-disable-line
import List from 'list.js'
// var ListFuzzySearch = require('imports?this=>window!../../node_modules/list.fuzzysearch.js/dist/list.fuzzysearch.js')
import Holder from 'holderjs'
import Bricks from 'bricks.js'

// Page modules
var apiRoutes = require('./api')
var getApiData = require('./get-api-data')
var templating = require('./template-render')
// var Spinner = require('spin.js')

import Find from 'lodash/collection/find'

// Spinner
// var spin = document.getElementById('spin')
// var loading = new Spinner().spin(spin)

// Run Holder
Holder.run({})

// Get API data using promise
getApiData.data(apiRoutes.needs)
  .then(function (result) {
    var needsFromApi = result.data
    // var theData = { 'needs': needsFromApi }

    console.log(needsFromApi)

    // List.js
    var options = {
      valueNames: [ 'id', 'type', 'serviceProviderId', 'description' ],
      item: '

',
      plugins: [
        // ListFuzzySearch()
      ]
    }

    const theList = new List('js-card-search', options, needsFromApi)

    // Bricks.js
    const sizes = [
      { columns: 1, gutter: 20 }, // assumed to be mobile, because of the missing mq property
      { mq: '360px', columns: 1, gutter: 20 },
      { mq: '480px', columns: 2, gutter: 20 },
      { mq: '600px', columns: 2, gutter: 20 },
      { mq: '800px', columns: 3, gutter: 20 }
    ]

    const cardLayout = Bricks({
      container: '.list',
      packed: 'data-packed', // if not prefixed with 'data-', it will be added
      sizes: sizes
    })

    cardLayout
      .resize(true) // bind resize handler
      .pack() // pack initial items

    // List.js Triggers
    theList.on('sortStart', () =>
      cardLayout.pack()
    )

    theList.on('searchComplete', () =>
      cardLayout.pack()
    )

    // Filtering
    var b
    var filters = document.querySelectorAll('.js-filter-item')
    var activeFilters = []

    // Add click listener to each item
    for (b = 0; b < filters.length; b++) {
      filters[b].addEventListener('click', function (event) {
        var getFilter = this.getAttribute('data-filter')
        event.preventDefault()

        console.log('filter clicked: ' + getFilter)

        if (getFilter === 'all') {
          resetFiltering()
        } else {
          if (this.classList.contains('is-active')) {
            console.log('this filter is already active')
            this.classList.remove('is-active')
            activeFilters.splice(activeFilters.indexOf(getFilter), 1)
            runFiltering()
          } else {
            console.log('this filter is not already active')

            document.querySelector('.js-filter-item-all').classList.remove('is-active')
            this.classList.add('is-active')
            activeFilters.push(getFilter)
            runFiltering()
          }
        }
      })
    }

    var runFiltering = function () {
      console.log('active filters: ' + activeFilters)

      if (activeFilters.length === 0) {
        console.log('no active filters, abort and reset')
        resetFiltering()
        return
      }

      console.log('test')

      theList.filter(function (item) {
        if (activeFilters.length > 0) {
          return (activeFilters.indexOf(item.values().type)) > -1
        }
        return true
      })

      cardLayout.pack()
    }

    var resetFiltering = function () {
      // Reset active states
      var c
      var filters = document.querySelectorAll('.js-filter-item')

      activeFilters = []

      console.log('reset filter function')
      console.log('active filters (there should be none): ' + activeFilters)

      for (c = 0; c < filters.length; c++) {
        filters[c].classList.remove('is-active')
      }

      document.querySelector('.js-filter-item-all').classList.add('is-active')

      // Reset filter & layout
      theList.filter()
      cardLayout.pack()
    }

    // Full detail view
    var a
    var items = document.querySelectorAll('.list li')

    // Add click listener to each item
    for (a = 0; a < items.length; a++) {
      items[a].addEventListener('click', function (event) {
        event.preventDefault()
        openCard(this)
      })
    }

    var openCard = function (el) {
      var theId = el.getElementsByClassName('id')[0].textContent
      var cardData = Find(needsFromApi, function (o) { return o.id === theId })

      // hide search
      document.querySelector('#js-card-search').classList.remove('is-active')
      document.querySelector('#js-card-search').classList.add('is-hidden')

      // Append object name for Hogan
      var theTemplateData = { card: cardData }

      var callback = function () {
        document.querySelector('.js-card-detail').classList.remove('is-hidden')
        document.querySelector('.js-card-detail').classList.add('is-active')

        window.scrollTo(0, 0)
      }

      templating.renderTemplate('js-card-detail-tpl', theTemplateData, 'js-card-detail-output', callback)
    }
  })

// Example bricks.js api
/*
cardSort
  .on('pack', () => console.log('ALL grid items packed.'))
  .on('update', () => console.log('NEW grid items packed.'))
  .on('resize', size => console.log('The grid has be re-packed to accommodate a new BREAKPOINT.'))
*/
<|endoftext|>