<commit_before>/**
 *
 * Copyright 2016, Institute for Systems Biology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

define (['jquery', 'd3', 'vizhelpers'],
function($, d3, vizhelpers) {
    var helpers = Object.create(vizhelpers, {});
    return {
        create_scatterplot: function(svg, data, domain, range, xLabel, yLabel, xParam, yParam, colorBy, legend, width, height, cohort_set) {
            var margin = {top: 10, bottom: 50, left: 50, right: 10};
            var yVal = function(d) {
                if (helpers.isValidNumber(d[yParam])) {
                    return d[yParam];
                } else {
                    d[yParam] = range[1];
                    return range[1];
                }
            };

            var yScale = d3.scale.linear().range([height-margin.bottom, margin.top]).domain(range);
            var yMap = function(d) { if(typeof(Number(d.y)) == "number"){return yScale(yVal(d));} else { return 0;}};
            var yAxis = d3.svg.axis()
                    .scale(yScale)
                    .orient("left")
                    .tickSize(-width - margin.left - margin.right, 0, 0);

            var xVal = function(d) {
                    if (helpers.isValidNumber(d[xParam])) {
                        return d[xParam];
                    } else {
                        d[xParam] = domain[1];
                        return domain[1];
                    }
                };

            var xScale = d3.scale.linear().range([margin.left, width]).domain(domain);
            var xMap = function(d) {if(typeof(Number(d.x)) == "number"){return xScale(xVal(d));} else { return 0;}};
            var xAxis = d3.svg.axis()
                    .scale(xScale)
                    .orient("bottom")
                    .tickSize(-height - margin.top - margin.bottom, 0, 0);

            var colorVal = function(d) {
                if (colorBy == 'cohort') {
                    return d['cohort'][0];
                }
                return d[colorBy];
            };
            var name_domain = $.map(data, function(d) {
                return d[colorBy];
            });
            var color = d3.scale.ordinal()
                .domain(name_domain)
                .range(helpers.color_map(name_domain.length));

            var plot_area = svg.append('g')
                .attr('clip-path', 'url(#plot_area_clip)');

            plot_area.append('clipPath')
                .attr('id', 'plot_area_clip')
                .append('rect')
                .attr('height', height-margin.top-margin.bottom)
                .attr('width', width)
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            // Highlight the selected circles.
            var brushmove = function(p) {
                var sample_list = [];
                var e = brush.extent();

                var plot_id = $(svg[0]).parents('.plot').attr('id').split('-')[1];
                svg.selectAll("circle").classed("selected", function(d) {
                    return e[0][0] <= d[xParam] && d[xParam] <= e[1][0]
                        && e[0][1] <= d[yParam] && d[yParam] <= e[1][1]
                        && !$(this).is('.hidden');
                    });
                var selected_samples = $('svg circle.selected');
                selected_samples.each(function(){ sample_list.push(this.id); });
                var patient_list = $.map(sample_list, function(d) { return d.substr(0, 12); })
                    .filter(function(item, i, a) { return i == a.indexOf(item); });

                sample_form_update(e, selected_samples.length, patient_list.length, sample_list);
            };

            // If the brush is empty, select all circles.
            var brushend = function() {
//                if (brush.empty()) svg.selectAll(".hidden").classed("hidden", false);
            };

            var brush = d3.svg.brush()
                .x(xScale)
                .y(yScale)
                .on('brushstart', function(){ svg.selectAll('.extent').style("fill", "rgba(40,130,50,0.5");})
                .on('brush', brushmove)
                .on('brushend', brushend);

            var transformer = function(d) {
                return 'translate(' + xMap(d) + ',' + yMap(d) + ')';
            };

            var zoomer = function() {
                svg.select('.x.axis').call(xAxis);
                svg.select('.y.axis').call(yAxis);
                plot_area.selectAll('circle').attr('transform', transformer);
            };

            var zoom = d3.behavior.zoom()
                .x(xScale)
                .y(yScale)
                .on('zoom', zoomer);

            var zoom_area = svg.append('g')
                .attr('class', 'zoom_area')
                .append('rect')
                .attr('width', width)
                .attr('height', height)
                .style('opacity', '0')
                .call(zoom);

            plot_area.selectAll('.dot')
                .data(data)
                .enter().append('circle')
                .attr('class', function(d) { return d[colorBy]; })
                .style('fill', function(d) { return color(colorVal(d)); })
                .attr('transform', transformer)
                .attr('r', 2)
                .attr('id', function(d) { return d['sample_id']; });

            // append axes
            svg.append('g')
                .attr('class', 'y axis')
                .attr('transform', 'translate(' + margin.left + ',0)')
                .call(yAxis);

            svg.append('g')
                .attr('class', 'x axis')
                .attr('transform', 'translate(0,' + (height - margin.bottom) + ')')
                .call(xAxis);

            // append axes labels
            svg.append('text')
                .attr('class', 'x label')
                .attr('text-anchor', 'middle')
                .attr('transform', 'translate(' + (width/2) + ',' + (height - 10) + ')')
                .text(xLabel);

            svg.append('text')
                .attr('class', 'y label')
                .attr('text-anchor', 'middle')
                .attr('transform', 'rotate(-90) translate(' + (-1 * (height/2)) + ',10)')
                .text(yLabel);

            var legend_item_height = 28;

            legend = legend.attr('height', legend_item_height * color.domain().length + 30);
            legend.append('text')
                .attr('x', 0)
                .attr('y', 20)
                .text('Legend');
            legend = legend.selectAll('.legend')
                .data(color.domain())
                .enter().append('g')
                .attr('class', 'legend')
                .attr("transform", function(d, i) { return "translate(0," + (((i+1) * 20) + 10) + ")"; });

            legend.append('rect')
                .attr('width', 20)
                .attr('height', 20)
                .attr('class', 'selected')
                .style('stroke', color)
                .style('stroke-width', 1)
                .style('fill', color)
                .on('click', helpers.toggle_selection);

            legend.append('text')
                .attr('x', 25)
                .attr('y', 15)
                .text(function(d) {
                    if (d != null) {
                        if (colorBy == 'cohort') {
                            for (var i = 0; i < cohort_set.length; i++) {
                                if (cohort_set[i]['id'] == d) { return cohort_set[i]['name']; }
                            }
                        } else {
                            return d;
                        }
                    } else {
                        return 'NA';
                    }
                });

            var check_selection_state = function(obj) {
                if (obj) {

                    // Remove zoom area
                    svg.selectAll('.zoom_area').remove();

                    // Append new brush event listeners to plot area only
                    plot_area.append('g')
                        .attr('class', 'brush')
                        .call(brush);
                } else {
                    var plot_id = $(svg[0]).parents('.plot').attr('id').split('-')[1];
                    // Clear selections
                    $(svg[0]).parents('.plot').find('.selected-samples-count').html('Number of Samples: ' + 0);
                    $(svg[0]).parents('.plot').find('.selected-patients-count').html('Number of Participants: ' + 0);
                    $('#save-cohort-'+plot_id+'-modal input[name="samples"]').attr('value', []);
                    svg.selectAll('.selected').classed('selected', false);
                    $(svg[0]).parents('.plot').find('.save-cohort-card').hide();

                    // Remove brush event listener plot area
                    plot_area.selectAll('.brush').remove();

                    // Append new zoom area
                    zoom_area = svg.append('g')
                        .attr('class', 'zoom_area')
                        .append('rect')
                        .attr('width', width)
                        .attr('height', height)
                        .style('opacity', '0')
                        .call(zoom);

                }
            };

            /*
                Update the sample cohort bar update
             */
            function sample_form_update(extent, total_samples, total_patients, sample_list){
                var plot_id = $(svg[0]).parents('.plot').attr('id').split('-')[1];
                $(svg[0]).parents('.plot').find('.selected-samples-count').html('Number of Samples: ' + total_samples);
                $(svg[0]).parents('.plot').find('.selected-patients-count').html('Number of Participants: ' + total_patients);
                $('#save-cohort-' + plot_id + '-modal input[name="samples"]').attr('value', sample_list);
                $(svg[0]).parents('.plot')
                    .find('.save-cohort-card').show()
                    .attr('style', 'position:absolute; top: '+ (yScale(extent[1][1]) + 180) +'px; left:' +(xScale(extent[1][0])+ 40)+'px;');

                if (total_samples > 0){
                    $(svg[0]).parents('.plot')
                        .find('.save-cohort-card').find('.btn').prop('disabled', false);
                } else {
                    $(svg[0]).parents('.plot')
                        .find('.save-cohort-card').find('.btn').prop('disabled', true);
                }
            }

            function resize() {
                width = svg.node().parentNode.offsetWidth - 10;
                //TODO resize plot
            }

            function check_selection_state_wrapper(bool){
                check_selection_state(bool);
            }

            return {
                resize                : resize,
                check_selection_state : check_selection_state_wrapper
            }
        }
    };
});
<commit_msg>#1551<commit_after>/**
 *
 * Copyright 2016, Institute for Systems Biology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

define (['jquery', 'd3', 'vizhelpers'],
function($, d3, vizhelpers) {
    var helpers = Object.create(vizhelpers, {});
    return {
        create_scatterplot: function(svg, data, domain, range, xLabel, yLabel, xParam, yParam, colorBy, legend, width, height, cohort_set) {
            var margin = {top: 10, bottom: 50, left: 50, right: 10};
            var yVal = function(d) {
                if (helpers.isValidNumber(d[yParam])) {
                    return d[yParam];
                } else {
                    d[yParam] = range[1];
                    return range[1];
                }
            };

            var yScale = d3.scale.linear().range([height-margin.bottom, margin.top]).domain(range);
            var yMap = function(d) { if(typeof(Number(d.y)) == "number"){return yScale(yVal(d));} else { return 0;}};
            var yAxis = d3.svg.axis()
                    .scale(yScale)
                    .orient("left")
                    .tickSize(-width - margin.left - margin.right, 0, 0);

            var xVal = function(d) {
                    if (helpers.isValidNumber(d[xParam])) {
                        return d[xParam];
                    } else {
                        d[xParam] = domain[1];
                        return domain[1];
                    }
                };

            var xScale = d3.scale.linear().range([margin.left, width]).domain(domain);
            var xMap = function(d) {if(typeof(Number(d.x)) == "number"){return xScale(xVal(d));} else { return 0;}};
            var xAxis = d3.svg.axis()
                    .scale(xScale)
                    .orient("bottom")
                    .tickSize(-height - margin.top - margin.bottom, 0, 0);

            var colorVal = function(d) {
                if (colorBy == 'cohort') {
                    return d['cohort'][0];
                }
                return d[colorBy];
            };
            var name_domain = $.map(data, function(d) {
                return d[colorBy];
            });
            var color = d3.scale.ordinal()
                .domain(name_domain)
                .range(helpers.color_map(name_domain.length));

            var plot_area = svg.append('g')
                .attr('clip-path', 'url(#plot_area_clip)');

            plot_area.append('clipPath')
                .attr('id', 'plot_area_clip')
                .append('rect')
                .attr('height', height-margin.top-margin.bottom)
                .attr('width', width)
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            // Highlight the selected circles.
            var brushmove = function(p) {
                var sample_list = [];
                var e = brush.extent();

                var plot_id = $(svg[0]).parents('.plot').attr('id').split('-')[1];
                svg.selectAll("circle").classed("selected", function(d) {
                    return e[0][0] <= d[xParam] && d[xParam] <= e[1][0]
                        && e[0][1] <= d[yParam] && d[yParam] <= e[1][1]
                        && !$(this).is('.hidden');
                    });
                var selected_samples = $('svg circle.selected');
                selected_samples.each(function(){ sample_list.push(this.id); });
                var patient_list = $.map(sample_list, function(d) { return d.substr(0, 12); })
                    .filter(function(item, i, a) { return i == a.indexOf(item); });

                sample_form_update(e, selected_samples.length, patient_list.length, sample_list);
            };

            // If the brush is empty, select all circles.
            var brushend = function() {
//                if (brush.empty()) svg.selectAll(".hidden").classed("hidden", false);
            };

            var brush = d3.svg.brush()
                .x(xScale)
                .y(yScale)
                .on('brushstart', function(){ svg.selectAll('.extent').style("fill", "rgba(40,130,50,0.5");})
                .on('brush', brushmove)
                .on('brushend', brushend);

            var transformer = function(d) {
                return 'translate(' + xMap(d) + ',' + yMap(d) + ')';
            };

            var zoomer = function() {
                svg.select('.x.axis').call(xAxis);
                svg.select('.y.axis').call(yAxis);
                plot_area.selectAll('circle').attr('transform', transformer);
            };

            var zoom = d3.behavior.zoom()
                .x(xScale)
                .y(yScale)
                .on('zoom', zoomer);

            var zoom_area = svg.append('g')
                .attr('class', 'zoom_area')
                .append('rect')
                .attr('width', width)
                .attr('height', height)
                .style('opacity', '0')
                .call(zoom);

            plot_area.selectAll('.dot')
                .data(data)
                .enter().append('circle')
                .attr('class', function(d) { return d[colorBy]; })
                .style('fill', function(d) { return color(colorVal(d)); })
                .attr('transform', transformer)
                .attr('r', 2)
                .attr('id', function(d) { return d['sample_id']; });

            // append axes
            svg.append('g')
                .attr('class', 'y axis')
                .attr('transform', 'translate(' + margin.left + ',0)')
                .call(yAxis);

            svg.append('g')
                .attr('class', 'x axis')
                .attr('transform', 'translate(0,' + (height - margin.bottom) + ')')
                .call(xAxis);

            // append axes labels
            svg.append('text')
                .attr('class', 'x label')
                .attr('text-anchor', 'middle')
                .attr('transform', 'translate(' + (width/2) + ',' + (height - 10) + ')')
                .text(xLabel);

            svg.append('text')
                .attr('class', 'y label')
                .attr('text-anchor', 'middle')
                .attr('transform', 'rotate(-90) translate(' + (-1 * (height/2)) + ',10)')
                .text(yLabel);

            var legend_item_height = 28;

            legend = legend.attr('height', legend_item_height * color.domain().length + 30);
            legend.append('text')
                .attr('x', 0)
                .attr('y', 20)
                .text('Legend');
            legend = legend.selectAll('.legend')
                .data(color.domain())
                .enter().append('g')
                .attr('class', 'legend')
                .attr("transform", function(d, i) { return "translate(0," + (((i+1) * 20) + 10) + ")"; });

            legend.append('rect')
                .attr('width', 20)
                .attr('height', 20)
                .attr('class', 'selected')
                .style('stroke', color)
                .style('stroke-width', 1)
                .style('fill', color)
                .on('click', helpers.toggle_selection);

            legend.append('text')
                .attr('x', 25)
                .attr('y', 15)
                .text(function(d) {
                    if (d != null) {
                        if (colorBy == 'cohort') {
                            if (d.isArray()) {
                                var cohort_name_label = "";
                                for (var i = 0; i < d.length; i++) {
                                    for (var j = 0; j < cohort_set.length; j++) {
                                        if (cohort_set[j]['id'] == d[i]) { cohort_name_label += cohort_set[i]['name'] + ','; }
                                    }
                                }
                                return cohort_name_label.slice(0,-1);
                            } else {
                                for (var i = 0; i < cohort_set.length; i++) {
                                    if (cohort_set[i]['id'] == d) { return cohort_set[i]['name']; }
                                }
                            }
                        } else {
                            return d;
                        }
                    } else {
                        return 'NA';
                    }
                });

            var check_selection_state = function(obj) {
                if (obj) {

                    // Remove zoom area
                    svg.selectAll('.zoom_area').remove();

                    // Append new brush event listeners to plot area only
                    plot_area.append('g')
                        .attr('class', 'brush')
                        .call(brush);
                } else {
                    var plot_id = $(svg[0]).parents('.plot').attr('id').split('-')[1];
                    // Clear selections
                    $(svg[0]).parents('.plot').find('.selected-samples-count').html('Number of Samples: ' + 0);
                    $(svg[0]).parents('.plot').find('.selected-patients-count').html('Number of Participants: ' + 0);
                    $('#save-cohort-'+plot_id+'-modal input[name="samples"]').attr('value', []);
                    svg.selectAll('.selected').classed('selected', false);
                    $(svg[0]).parents('.plot').find('.save-cohort-card').hide();

                    // Remove brush event listener plot area
                    plot_area.selectAll('.brush').remove();

                    // Append new zoom area
                    zoom_area = svg.append('g')
                        .attr('class', 'zoom_area')
                        .append('rect')
                        .attr('width', width)
                        .attr('height', height)
                        .style('opacity', '0')
                        .call(zoom);

                }
            };

            /*
                Update the sample cohort bar update
             */
            function sample_form_update(extent, total_samples, total_patients, sample_list){
                var plot_id = $(svg[0]).parents('.plot').attr('id').split('-')[1];
                $(svg[0]).parents('.plot').find('.selected-samples-count').html('Number of Samples: ' + total_samples);
                $(svg[0]).parents('.plot').find('.selected-patients-count').html('Number of Participants: ' + total_patients);
                $('#save-cohort-' + plot_id + '-modal input[name="samples"]').attr('value', sample_list);
                $(svg[0]).parents('.plot')
                    .find('.save-cohort-card').show()
                    .attr('style', 'position:absolute; top: '+ (yScale(extent[1][1]) + 180) +'px; left:' +(xScale(extent[1][0])+ 40)+'px;');

                if (total_samples > 0){
                    $(svg[0]).parents('.plot')
                        .find('.save-cohort-card').find('.btn').prop('disabled', false);
                } else {
                    $(svg[0]).parents('.plot')
                        .find('.save-cohort-card').find('.btn').prop('disabled', true);
                }
            }

            function resize() {
                width = svg.node().parentNode.offsetWidth - 10;
                //TODO resize plot
            }

            function check_selection_state_wrapper(bool){
                check_selection_state(bool);
            }

            return {
                resize                : resize,
                check_selection_state : check_selection_state_wrapper
            }
        }
    };
});
<|endoftext|>


<commit_before>// Template InputValidation.js

// include api.js

var bundle = context.getVariable('bundle');
var target;
var path = context.getVariable("proxy.pathsuffix").replace(/\/$/, '');
var resource = bundle.policify.getResourceForPath(api, path);
print('path', path, 'resource', resource);
var verb = context.getVariable("request.verb").toLowerCase();
var ParameterException = {};
var parameters;

if (resource) {

  if(!('parameters' in api["paths"][resource][verb])) {
      parameters = [];
  } else {
      parameters = api["paths"][resource][verb]["parameters"];
  }

  try {
      // loop through all defined parameters, throw exception when something fails
      parameters.forEach(function(parameter) {

          // Get values of dynamic parameters
          var pSchema = bundle.policify.paramToSchema(parameter);

          var pathParamValue = context.getVariable('pathParam.' + parameter.name);
          print(parameter.name, pathParamValue, JSON.stringify(pSchema));

          if (!(parameter["in"] === "query" || parameter["in"] === "path")) {
              // we only parse query and path params for now
              return false;
          }
          print("Going for parameter " + parameter.name);

          var wrappedParamValue = {};
          wrappedParamValue[parameter.name] =
            (pathParamValue)
            ?
            pathParamValue
            :
            context.proxyRequest.queryParams[parameter.name];

          var isValid = bundle.policify.validateSchema(wrappedParamValue, pSchema);
          print('valid?', isValid, JSON.stringify(wrappedParamValue));
          if (isValid) {
            print("Parameter value is conform the schema");
          } else {
            var err = bundle.policify.getLastError();
            print("Parameter does not validate with the parameter schema");
            print("Error " + JSON.stringify(err));
            throw ParameterException;
          }

          // check if the parameter is required
          // if("required" in parameter && parameter['required'] === true && !(parameter['name'] in context.proxyRequest.queryParams)) {
          //     print("Parameter was required, but not found");
          //     throw ParameterException;
          // }
          //
          // // check if the param is set
          // if(!(parameter['name'] in context.proxyRequest.queryParams)) {
          //     print("Parameter was not required, and also not set, skipping");
          //
          //     // no further processing needed, param was not set
          //     return false
          // }
          //
          // // check if the param type is correct
          // print("Value is: " + context.proxyRequest.queryParams[parameter.name]);
          // print("Checking parameter type, should be: " + parameter.type + ", is: " + typeof(context.proxyRequest.queryParams[parameter.name]));
          // switch(parameter.type) {
          //     case "integer":
          //         if(typeof(context.proxyRequest.queryParams[parameter.name]) !== "number") {
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case "null":
          //         // null is of type 'object':
          //         // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/typeof
          //         if(typeof(context.proxyRequest.queryParams[parameter.name]) !== 'object') {
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     // is this even possible?
          //     case "array":
          //         if(!context.proxyRequest.queryParams[parameter.name].isArray()) {
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case "string":
          //         // apigee casts these into a list, see:
          //         if(typeof(context.proxyRequest.queryParams[parameter.name][0]) !== parameter.type) {
          //             print("Expected " + parameter.type + ", got: " + typeof(context.proxyRequest.queryParams[parameter.name]))
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case "object":
          //     case "boolean":
          //     case "number":
          //         if(typeof(context.proxyRequest.queryParams[parameter.name]) !== parameter.type) {
          //             print("Expected " + parameter.type + ", got: " + typeof(context.proxyRequest.queryParams[parameter.name]))
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case 'default':
          //         // this is not a valid json schema type and/or covered by this parser
          //         print(parameter.name + " is not a valid json schema type");
          //         throw ParameterException;
          //     }
          // print("Parameter type is valid");
          //
          //
          // // if a pattern regex was set, check the input
          // if("pattern" in parameter && parameter["pattern"] !== "") {
          //     print("VALIDATE REGEX", context.proxyRequest.queryParams[parameter.name]);
          //     if (!checkRegex(context.proxyRequest.queryParams[parameter.name], parameter["pattern"])) {
          //         print("Regex check failed", parameter["pattern"]);
          //         throw ParameterException;
          //     }
          // }

      });
  } catch(e) {
      if(e !== ParameterException) {
          throw e;
      } else {
          // we got an error, let Apigee figure it out
          context.setVariable('INPUT.error', true);
      }
  }
} else {
  print('resource could not be found');
  context.setVariable('INPUT.error', true);
}
<commit_msg>use openapi-utils-param-to-schema<commit_after>// Template InputValidation.js

// include api.js

var bundle = context.getVariable('bundle');
var target;
var path = context.getVariable("proxy.pathsuffix").replace(/\/$/, '');
var resource = bundle.policify.getResourceForPath(api, path);
print('path', path, 'resource', resource);
var verb = context.getVariable("request.verb").toLowerCase();
var ParameterException = {};
var parameters;

if (resource) {

  if(!('parameters' in api["paths"][resource][verb])) {
      parameters = [];
  } else {
      parameters = api["paths"][resource][verb]["parameters"];
  }

  try {
      // loop through all defined parameters, throw exception when something fails
      parameters.forEach(function(parameter) {

          if (!(parameter["in"] === "query" || parameter["in"] === "path")) {
              // we only parse query and path params for now
              return false;
          }

          // Create schema from parameter definition
          var pSchema = bundle.policify.paramToSchema(parameter);
          var pathParamValue = context.getVariable('pathParam.' + parameter.name);
          print(parameter.name, pathParamValue, JSON.stringify(pSchema));

          var wrappedParamValue = {};
          if (pathParamValue) {
            wrappedParamValue[parameter.name] = pathParamValue;
          } else {
            wrappedParamValue[parameter.name] = context.proxyRequest.queryParams[parameter.name][0] || '';
          }

          // Validate against the schema.
          var isValid = bundle.policify.validateSchema(wrappedParamValue, pSchema);
          print('valid?', isValid, JSON.stringify(wrappedParamValue));
          if (isValid) {
            print("Parameter value is conform the parameter schema");
          } else {
            var err = bundle.policify.getLastError();
            print("Parameter does not validate with the parameter schema");
            print("Error " + JSON.stringify(err));
            throw ParameterException;
          }

          // check if the parameter is required
          // if("required" in parameter && parameter['required'] === true && !(parameter['name'] in context.proxyRequest.queryParams)) {
          //     print("Parameter was required, but not found");
          //     throw ParameterException;
          // }
          //
          // // check if the param is set
          // if(!(parameter['name'] in context.proxyRequest.queryParams)) {
          //     print("Parameter was not required, and also not set, skipping");
          //
          //     // no further processing needed, param was not set
          //     return false
          // }
          //
          // // check if the param type is correct
          // print("Value is: " + context.proxyRequest.queryParams[parameter.name]);
          // print("Checking parameter type, should be: " + parameter.type + ", is: " + typeof(context.proxyRequest.queryParams[parameter.name]));
          // switch(parameter.type) {
          //     case "integer":
          //         if(typeof(context.proxyRequest.queryParams[parameter.name]) !== "number") {
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case "null":
          //         // null is of type 'object':
          //         // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/typeof
          //         if(typeof(context.proxyRequest.queryParams[parameter.name]) !== 'object') {
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     // is this even possible?
          //     case "array":
          //         if(!context.proxyRequest.queryParams[parameter.name].isArray()) {
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case "string":
          //         // apigee casts these into a list, see:
          //         if(typeof(context.proxyRequest.queryParams[parameter.name][0]) !== parameter.type) {
          //             print("Expected " + parameter.type + ", got: " + typeof(context.proxyRequest.queryParams[parameter.name]))
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case "object":
          //     case "boolean":
          //     case "number":
          //         if(typeof(context.proxyRequest.queryParams[parameter.name]) !== parameter.type) {
          //             print("Expected " + parameter.type + ", got: " + typeof(context.proxyRequest.queryParams[parameter.name]))
          //             throw ParameterException;
          //         }
          //         break;
          //
          //     case 'default':
          //         // this is not a valid json schema type and/or covered by this parser
          //         print(parameter.name + " is not a valid json schema type");
          //         throw ParameterException;
          //     }
          // print("Parameter type is valid");
          //
          //
          // // if a pattern regex was set, check the input
          // if("pattern" in parameter && parameter["pattern"] !== "") {
          //     print("VALIDATE REGEX", context.proxyRequest.queryParams[parameter.name]);
          //     if (!checkRegex(context.proxyRequest.queryParams[parameter.name], parameter["pattern"])) {
          //         print("Regex check failed", parameter["pattern"]);
          //         throw ParameterException;
          //     }
          // }

      });
  } catch(e) {
      if(e !== ParameterException) {
          throw e;
      } else {
          // we got an error, let Apigee figure it out
          context.setVariable('INPUT.error', true);
      }
  }
} else {
  print('resource could not be found');
  context.setVariable('INPUT.error', true);
}
<|endoftext|>


<commit_before>var ws = require("nodejs-websocket"),
    express = require("express");

process.stdout.on("error", function(err) {
    console.log("ERROR:", err, err.code);
    switch (err.code) {
        case "EPIPE":
            break;
        default:
            process.exit(0);
    }
});

var app = express(),
    httpServer = require("http").createServer(app);

app.get("/test", function(req, res) {
    console.log(req);
});
httpServer.listen(process.env.PORT || 8000);

var wsServer = null;
var settings = {
        pingInterval: 30*1000, // ms
        sessionTimeout: 2*60*1000 // ms
};
var errors = {
    msgFailed: "Message construction failed.",
    sendFailed: "Message sending failed.",
    parseFailed: "Message parse failed.",
    malformed: "Message malformed.",
    unknownHeader: "Unknown header."
};

// id: {connections: [], timeout: f}
var sessions = {};

// sessionId: {contact: "", tier: "", region: ""}
var scrims = {};
var tiers = ["Low", "Mid", "High", "High+", "High++"];
var regions = ["SEA", "NA", "EU"];

function message(header, body) {
    var m = {header: header.toUpperCase(), body: body, timestamp: +new Date()};
    try {
        m = JSON.stringify(m);
    } catch (e) {
        return {message: null, error: e};
    } finally {
        return {message: m, error: null};
    }
}

function send(sid, header, body) {
    var m = message(header, body);
    if (m.error) {
        console.log("Error:", errors.msgFailed, m.error);
        return;
    }
    if (!(sid in sessions)) {
        console.log("Error:", errors.sendFailed, "Session with that ID not found.", sid);
        return;
    }
    console.log(sid, "<-", header, body);
    sessions[sid].connections.forEach(function(c) {
        try {
            if (c.readyState === c.OPEN) c.send(m.message);
        } catch(err) {
            console.log("Error:", errors.sendFailed, err);
        }
    });
}

function broadcast(header, body) {
    for (sid in sessions) {
        send(sid, header, body);
    }
}

function pinger() {
    setInterval(function () {
        broadcast("PING", null);
    }, settings.pingInterval);
}

function merge(conn, sid) {
    if (conn.sessionId === sid) return;
    if (!(sid in sessions)) {
        sessions[sid] = {connections: [conn], timeout: function() {}};
        delete scrims[conn.sessionId];
        delete sessions[conn.sessionId];
        conn.sessionId = sid;
        return;
    }

    delete sessions[conn.sessionId];
    clearTimeout(sessions[sid].timeout);
    sessions[sid].connections.push(conn);

    if (conn.sessionId in scrims) {
        scrims[sid] = scrims[conn.sessionId];
        delete scrims[conn.sessionId];
        update();
    }
    conn.sessionId = sid;
}

function update() {
    var data = [];
    for (k in scrims) {
        data.push(scrims[k]);
    }
    broadcast("UPDATE", data);
    console.log("Scrims:", data);
}

function handle(conn, data) {
    if (!("header" in data) || !("body" in data)) {
        send(conn.sessionId, "ERROR", errors.malformed);
        return;
    }
    data.header = data.header || "";
    data.body = data.body || "";

    switch (data.header.toUpperCase()) {
        case "IDENT":
            var oldSid = data.body;
            if (oldSid) {
                console.log("Switch", conn.sessionId, "to", oldSid);
                merge(conn, oldSid);
            }
            break;
        case "SET":
            if (typeof data.body !== "object") {
                send(conn.sessionId, "ERROR", errors.malformed);
                break;
            }
            if (!("tier" in data.body) || !("region" in data.body) || !("contact" in data.body)) {
                send(conn.sessionId, "ERROR", errors.malformed);
                break;
            }
            if (tiers.indexOf(data.body.tier) < 0 || regions.indexOf(data.body.region) < 0 || data.body.contact.length > 20) {
                send(conn.sessionId, "ERROR", errors.malformed);
                break;
            }
            scrims[conn.sessionId] = {contact: data.body.contact, region: data.body.region, tier: data.body.tier};
            update();
            break;
        case "CLEAR":
            delete scrims[conn.sessionId];
            update();
            break;
        case "PONG":
            break;
        case "SESSIONS":
            console.log(Object.keys(sessions));
            break;
        default:
            send(conn.sessionId, "ERROR", errors.unknownHeader + ": " + data.header);
    }
}

pinger();
wsServer = ws.createServer(function(conn) {
    conn.id = uuid();
    conn.sessionId = uuid();
    while (conn.readyState == conn.CONNECTING) {}
    sessions[conn.sessionId] = {connections: [conn], timeout: function() {}};
    console.log(conn.sessionId, "connected.");
    send(conn.sessionId, "IDENT", conn.sessionId);
    update();

    conn.on("text", function(str) {
        var data;
        try {
            data = JSON.parse(str);
        } catch(err) {
            console.log("Error:", errors.parseFailed, err);
            return;
        }
        if (!data) return;
        console.log("Received:", data);
        handle(conn, data);
    });

    conn.on("close", function(code, reason) {
        console.log(conn.id, "disconnected:", code, reason);
        if (conn.sessionId in sessions) {
            for (var i = 0; i < sessions[conn.sessionId].connections.length; i++) {
                var c = sessions[conn.sessionId].connections[i];
                if (c.id === conn.id) {
                    sessions[conn.sessionId].connections.splice(i, 1);
                    break;
                }
            }
            if (sessions[conn.sessionId].connections.length < 1) {
                sessions[conn.sessionId].timeout = setTimeout(function() {
                    delete scrims[conn.sessionId];
                    delete sessions[conn.sessionId];
                    update();
                }, settings.sessionTimeout);
            }
        }
    });
}).listen(httpServer);

function uuid(a){
    return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,uuid)
}
<commit_msg>Remove wait on connection<commit_after>var ws = require("nodejs-websocket"),
    express = require("express");

process.stdout.on("error", function(err) {
    console.log("ERROR:", err, err.code);
    switch (err.code) {
        case "EPIPE":
            break;
        default:
            process.exit(0);
    }
});

var app = express(),
    httpServer = require("http").createServer(app);

app.get("/test", function(req, res) {
    console.log(req);
});
httpServer.listen(process.env.PORT || 8000);

var wsServer = null;
var settings = {
        pingInterval: 30*1000, // ms
        sessionTimeout: 2*60*1000 // ms
};
var errors = {
    msgFailed: "Message construction failed.",
    sendFailed: "Message sending failed.",
    parseFailed: "Message parse failed.",
    malformed: "Message malformed.",
    unknownHeader: "Unknown header."
};

// id: {connections: [], timeout: f}
var sessions = {};

// sessionId: {contact: "", tier: "", region: ""}
var scrims = {};
var tiers = ["Low", "Mid", "High", "High+", "High++"];
var regions = ["SEA", "NA", "EU"];

function message(header, body) {
    var m = {header: header.toUpperCase(), body: body, timestamp: +new Date()};
    try {
        m = JSON.stringify(m);
    } catch (e) {
        return {message: null, error: e};
    } finally {
        return {message: m, error: null};
    }
}

function send(sid, header, body) {
    var m = message(header, body);
    if (m.error) {
        console.log("Error:", errors.msgFailed, m.error);
        return;
    }
    if (!(sid in sessions)) {
        console.log("Error:", errors.sendFailed, "Session with that ID not found.", sid);
        return;
    }
    console.log(sid, "<-", header, body);
    sessions[sid].connections.forEach(function(c) {
        try {
            if (c.readyState === c.OPEN) c.send(m.message);
        } catch(err) {
            console.log("Error:", errors.sendFailed, err);
        }
    });
}

function broadcast(header, body) {
    for (sid in sessions) {
        send(sid, header, body);
    }
}

function pinger() {
    setInterval(function () {
        broadcast("PING", null);
    }, settings.pingInterval);
}

function merge(conn, sid) {
    if (conn.sessionId === sid) return;
    if (!(sid in sessions)) {
        sessions[sid] = {connections: [conn], timeout: function() {}};
        delete scrims[conn.sessionId];
        delete sessions[conn.sessionId];
        conn.sessionId = sid;
        return;
    }

    delete sessions[conn.sessionId];
    clearTimeout(sessions[sid].timeout);
    sessions[sid].connections.push(conn);

    if (conn.sessionId in scrims) {
        scrims[sid] = scrims[conn.sessionId];
        delete scrims[conn.sessionId];
        update();
    }
    conn.sessionId = sid;
}

function update() {
    var data = [];
    for (k in scrims) {
        data.push(scrims[k]);
    }
    broadcast("UPDATE", data);
    console.log("Scrims:", data);
}

function handle(conn, data) {
    if (!("header" in data) || !("body" in data)) {
        send(conn.sessionId, "ERROR", errors.malformed);
        return;
    }
    data.header = data.header || "";
    data.body = data.body || "";

    switch (data.header.toUpperCase()) {
        case "IDENT":
            var oldSid = data.body;
            if (oldSid) {
                console.log("Switch", conn.sessionId, "to", oldSid);
                merge(conn, oldSid);
            }
            break;
        case "SET":
            if (typeof data.body !== "object") {
                send(conn.sessionId, "ERROR", errors.malformed);
                break;
            }
            if (!("tier" in data.body) || !("region" in data.body) || !("contact" in data.body)) {
                send(conn.sessionId, "ERROR", errors.malformed);
                break;
            }
            if (tiers.indexOf(data.body.tier) < 0 || regions.indexOf(data.body.region) < 0 || data.body.contact.length > 20) {
                send(conn.sessionId, "ERROR", errors.malformed);
                break;
            }
            scrims[conn.sessionId] = {contact: data.body.contact, region: data.body.region, tier: data.body.tier};
            update();
            break;
        case "CLEAR":
            delete scrims[conn.sessionId];
            update();
            break;
        case "PONG":
            break;
        case "SESSIONS":
            console.log(Object.keys(sessions));
            break;
        default:
            send(conn.sessionId, "ERROR", errors.unknownHeader + ": " + data.header);
    }
}

pinger();
wsServer = ws.createServer(function(conn) {
    conn.id = uuid();
    conn.sessionId = uuid();
    sessions[conn.sessionId] = {connections: [conn], timeout: function() {}};
    console.log(conn.sessionId, "connected.");
    send(conn.sessionId, "IDENT", conn.sessionId);
    update();

    conn.on("text", function(str) {
        var data;
        try {
            data = JSON.parse(str);
        } catch(err) {
            console.log("Error:", errors.parseFailed, err);
            return;
        }
        if (!data) return;
        console.log("Received:", data);
        handle(conn, data);
    });

    conn.on("close", function(code, reason) {
        console.log(conn.id, "disconnected:", code, reason);
        if (conn.sessionId in sessions) {
            for (var i = 0; i < sessions[conn.sessionId].connections.length; i++) {
                var c = sessions[conn.sessionId].connections[i];
                if (c.id === conn.id) {
                    sessions[conn.sessionId].connections.splice(i, 1);
                    break;
                }
            }
            if (sessions[conn.sessionId].connections.length < 1) {
                sessions[conn.sessionId].timeout = setTimeout(function() {
                    delete scrims[conn.sessionId];
                    delete sessions[conn.sessionId];
                    update();
                }, settings.sessionTimeout);
            }
        }
    });
}).listen(httpServer);

function uuid(a){
    return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,uuid)
}
<|endoftext|>


<commit_before>/**
 * Form validation
 */
bolt.validation = (function () {

    /**
     * Basic legacy validation checking
     * Adapted from  http://www.sitepoint.com/html5-forms-javascript-constraint-validation-api/
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function legacyValidation(field) {
        var
            valid = true,
            val = field.value,
            type = field.getAttribute('type'),
            chkbox = type === 'checkbox' || type === 'radio',
            required = field.getAttribute('required'),
            minlength = field.getAttribute('minlength'),
            maxlength = field.getAttribute('maxlength'),
            pattern = field.getAttribute('pattern');

        // Disabled fields should not be validated
        if (field.disabled) {
            return valid;
        }

        /* jshint -W126 */

        // value required?
        valid = valid && (!required ||
            (chkbox && field.checked) ||
            (!chkbox && val !== "")
        );

        // minlength or maxlength set?
        valid = valid && (chkbox || (
            (!minlength || val.length >= minlength) &&
            (!maxlength || val.length <= maxlength)
        ));

        /* jshint +W126 */

        // Test pattern
        if (valid && pattern) {
            pattern = new RegExp('^(?:' + pattern + ')$');
            valid = pattern.test(val);
        }

        return valid;
    }

    /**
     * Adds error classes to field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function addErrorClass(field, isCkeditor) {
        $(field).addClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).addClass('cke_error');
        }
    }

    /**
     * Removes error classes from field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function removeErrorClass(field, isCkeditor) {
        $(field).removeClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).removeClass('cke_error');
        }
    }

    /**
     * Show alertbox
     *
     * @param {string} id - Id of the alertbox
     * @param {string} msg - Message text
     */
    function showAlertbox(id, msg) {
        var alertbox = bolt.data.editcontent.error.alertbox.subst({
            '%NOTICE_ID%': id,
            '%MESSAGE%': msg
        });

        $(alertbox)
            .hide()
            .insertAfter('.page-header')
            .slideDown('fast');
    }

    /**
     * Checks if value is a float
     *
     * @param {string} value - Value of field
     *
     * @returns {string} Error string on error or empty string
     */
    function checkFloat(value) {
        if (value !== '' && !value.match(/^[-+]?[0-9]*[,.]?[0-9]+([eE][-+]?[0-9]+)?$/)) {
            return bolt.data.validation.float;
        } else {
            return '';
        }
    }

    /**
     * Checks if a required value is set
     *
     * @param {string} value - Value of field
     * @param {boolean} required - Value is required
     *
     * @returns {string} Error string on error or empty string
     */
    function checkRequired(value, required) {
        if (required === true && value === '') {
            return bolt.data.validation.required;
        } else {
            return '';
        }
    }

    /**
     * Checks for minimum value
     *
     * @param {string} value - Value of field
     * @param {string} param - Minimum value
     *
     * @returns {string} Error string on error or empty string
     */
    function checkMin(value, minimum) {
        if (value !== '' && Number(value.replace(',', '.')) < minimum) {
            return bolt.data.validation.min.subst({'%MINVAL%': minimum});
        } else {
            return '';
        }
    }

    /**
     * Checks for maximum value
     *
     * @param {string} value - Value of field
     * @param {string} maximum - Maximum value
     *
     * @returns {string} Error string on error or empty string
     */
    function checkMax(value, maximum) {
        if (value !== '' && Number(value.replace(',', '.')) > maximum) {
            return bolt.data.validation.max.subst({'%MAXVAL%': maximum});
        } else {
            return '';
        }
    }

    /**
     * Validates a field
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function validate(field) {
        var hasNativeValidation = typeof field.willValidate !== 'undefined',
            isCkeditor,
            task,
            param,
            value = field.value,
            error,
            label;

        var validates = $(field).data('validate');
        if (validates) {
            for (task in validates) {
                param = validates[task];

                switch (task) {
                    case 'float':
                        error = checkFloat(value);
                        break;

                    case 'required':
                        error =  checkRequired(value, param);
                        break;

                    case 'min':
                        error = checkMin(value, param);
                        break;

                    case 'max':
                        error = checkMax(value, param);
                        break;

                    default:
                        console.log('UNKNOWN VALIDATION' + task + " -> " + param);
                }
                // Stop on first error
                if (error) {
                    // Insert label
                    label = $('label[for="' + field.id + '"]').contents().first().text().trim();
                    error = error.subst({'%FIELDNAME%': label ? label : field.name});

                    if (hasNativeValidation) {
                        field.setCustomValidity(error);
                    } else {
                        field.validity.valid = false;
                    }
                    break;
                } else {
                    if (hasNativeValidation) {
                        field.setCustomValidity('');
                    } else {
                        field.validity.valid = true;
                    }
                }
            }
        } else {
            // Is native browser validation available?
            if (hasNativeValidation) {
                // Native validation available
                if (field.nodeName === 'INPUT' && field.type !== field.getAttribute('type')) {
                    // Input type not supported! Use legacy JavaScript validation
                    field.setCustomValidity(legacyValidation(field) ? '' : 'error');
                }
                // Native browser check
                field.checkValidity();
            } else {
                // Native validation not available
                field.validity = field.validity || {};
                // Set to result of validation function
                field.validity.valid = legacyValidation(field);

                // If "invalid" events are required, trigger it here
            }

            // Special validation for CKEditor fields
            isCkeditor = field.nodeName === 'TEXTAREA' && $(field).hasClass('ckeditor');
            if (isCkeditor) {
                var editor = CKEDITOR.instances[field.id],
                    invalid;

                if (editor) {
                    invalid = editor._.required === true && editor.getData().trim() === '';
                    if (hasNativeValidation) {
                        field.setCustomValidity(invalid ? 'Required' : '');
                    } else {
                        field.validity.valid = !invalid;
                    }
                }
            }
        }

        var noticeID = 'notice--' + field.id;

        // First, remove any existing old notices
        $('#' + noticeID).remove();

        if (field.validity.valid) {
            removeErrorClass(field, isCkeditor);

            return true;
        } else {
            addErrorClass(field, isCkeditor);

            var msg = error || $(field).data('errortext');
            if (!msg) {
                msg = bolt.data.editcontent.error.msg.subst({'%FIELDNAME%': field.name});
            }
            showAlertbox(noticeID, msg);

            return false;
        }
    }

    return {
        /**
         * Validates all inputs of a form
         *
         * @param {Object} form - Form element
         * @returns {boolean}
         */
        run: function (form) {
            var formLength = form.elements.length,
                f,
                field,
                formvalid = true;

            // Loop all fields
            for (f = 0; f < formLength; f++) {
                field = form.elements[f];

                if (field.nodeName !== 'INPUT' && field.nodeName !== 'TEXTAREA' && field.nodeName !== 'SELECT') {
                    continue;
                }

                if (field.nodeName === 'INPUT') {
                    // Trim input values
                    field.value = field.value.trim();
                }

                if (validate(field) === false) {
                    formvalid = false;
                }
            }

            return formvalid;
        }
    };
} ());
<commit_msg>Add setValidity method<commit_after>/**
 * Form validation
 */
bolt.validation = (function () {

    /**
     * Basic legacy validation checking
     * Adapted from  http://www.sitepoint.com/html5-forms-javascript-constraint-validation-api/
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function legacyValidation(field) {
        var
            valid = true,
            val = field.value,
            type = field.getAttribute('type'),
            chkbox = type === 'checkbox' || type === 'radio',
            required = field.getAttribute('required'),
            minlength = field.getAttribute('minlength'),
            maxlength = field.getAttribute('maxlength'),
            pattern = field.getAttribute('pattern');

        // Disabled fields should not be validated
        if (field.disabled) {
            return valid;
        }

        /* jshint -W126 */

        // value required?
        valid = valid && (!required ||
            (chkbox && field.checked) ||
            (!chkbox && val !== "")
        );

        // minlength or maxlength set?
        valid = valid && (chkbox || (
            (!minlength || val.length >= minlength) &&
            (!maxlength || val.length <= maxlength)
        ));

        /* jshint +W126 */

        // Test pattern
        if (valid && pattern) {
            pattern = new RegExp('^(?:' + pattern + ')$');
            valid = pattern.test(val);
        }

        return valid;
    }

    /**
     * Adds error classes to field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function addErrorClass(field, isCkeditor) {
        $(field).addClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).addClass('cke_error');
        }
    }

    /**
     * Removes error classes from field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function removeErrorClass(field, isCkeditor) {
        $(field).removeClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).removeClass('cke_error');
        }
    }

    /**
     * Show alertbox
     *
     * @param {string} id - Id of the alertbox
     * @param {string} msg - Message text
     */
    function showAlertbox(id, msg) {
        var alertbox = bolt.data.editcontent.error.alertbox.subst({
            '%NOTICE_ID%': id,
            '%MESSAGE%': msg
        });

        $(alertbox)
            .hide()
            .insertAfter('.page-header')
            .slideDown('fast');
    }

    /**
     * Checks if value is a float
     *
     * @param {string} value - Value of field
     *
     * @returns {string} Error string on error or empty string
     */
    function checkFloat(value) {
        if (value !== '' && !value.match(/^[-+]?[0-9]*[,.]?[0-9]+([eE][-+]?[0-9]+)?$/)) {
            return bolt.data.validation.float;
        } else {
            return '';
        }
    }

    /**
     * Checks if a required value is set
     *
     * @param {string} value - Value of field
     * @param {boolean} required - Value is required
     *
     * @returns {string} Error string on error or empty string
     */
    function checkRequired(value, required) {
        if (required === true && value === '') {
            return bolt.data.validation.required;
        } else {
            return '';
        }
    }

    /**
     * Checks for minimum value
     *
     * @param {string} value - Value of field
     * @param {string} param - Minimum value
     *
     * @returns {string} Error string on error or empty string
     */
    function checkMin(value, minimum) {
        if (value !== '' && Number(value.replace(',', '.')) < minimum) {
            return bolt.data.validation.min.subst({'%MINVAL%': minimum});
        } else {
            return '';
        }
    }

    /**
     * Checks for maximum value
     *
     * @param {string} value - Value of field
     * @param {string} maximum - Maximum value
     *
     * @returns {string} Error string on error or empty string
     */
    function checkMax(value, maximum) {
        if (value !== '' && Number(value.replace(',', '.')) > maximum) {
            return bolt.data.validation.max.subst({'%MAXVAL%': maximum});
        } else {
            return '';
        }
    }

    /**
     * Set validity of a field
     *
     * @param {Object} field - Field element
     * @param {string} field - Error message or empty string if valid
     * @returns {boolean}
     */
    function setValidity(field, error) {
        if (typeof field.willValidate !== 'undefined') {
            field.setCustomValidity(error);
        } else {
            field.validity.valid = error === '';
        }
    }

    /**
     * Validates a field
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function validate(field) {
        var hasNativeValidation = typeof field.willValidate !== 'undefined',
            isCkeditor,
            task,
            param,
            value = field.value,
            error = '',
            label;

        var validates = $(field).data('validate');
        if (validates) {
            for (task in validates) {
                param = validates[task];

                switch (task) {
                    case 'float':
                        error = checkFloat(value);
                        break;

                    case 'required':
                        error =  checkRequired(value, param);
                        break;

                    case 'min':
                        error = checkMin(value, param);
                        break;

                    case 'max':
                        error = checkMax(value, param);
                        break;

                    default:
                        console.log('UNKNOWN VALIDATION' + task + " -> " + param);
                }
                // Stop on first error
                if (error) {
                    // Insert label
                    label = $('label[for="' + field.id + '"]').contents().first().text().trim();
                    error = error.subst({'%FIELDNAME%': label ? label : field.name});
                }
                setValidity(field, error);
            }
        } else {
            // Is native browser validation available?
            if (hasNativeValidation) {
                // Native validation available
                if (field.nodeName === 'INPUT' && field.type !== field.getAttribute('type')) {
                    // Input type not supported! Use legacy JavaScript validation
                    field.setCustomValidity(legacyValidation(field) ? '' : 'error');
                }
                // Native browser check
                field.checkValidity();
            } else {
                // Native validation not available
                field.validity = field.validity || {};
                // Set to result of validation function
                field.validity.valid = legacyValidation(field);

                // If "invalid" events are required, trigger it here
            }

            // Special validation for CKEditor fields
            isCkeditor = field.nodeName === 'TEXTAREA' && $(field).hasClass('ckeditor');
            if (isCkeditor) {
                var editor = CKEDITOR.instances[field.id],
                    invalid;

                if (editor) {
                    invalid = editor._.required === true && editor.getData().trim() === '';
                    setValidity(field, invalid ? 'Required' : '');
                }
            }
        }

        var noticeID = 'notice--' + field.id;

        // First, remove any existing old notices
        $('#' + noticeID).remove();

        if (field.validity.valid) {
            removeErrorClass(field, isCkeditor);

            return true;
        } else {
            addErrorClass(field, isCkeditor);

            var msg = error || $(field).data('errortext');
            if (!msg) {
                msg = bolt.data.editcontent.error.msg.subst({'%FIELDNAME%': field.name});
            }
            showAlertbox(noticeID, msg);

            return false;
        }
    }

    return {
        /**
         * Validates all inputs of a form
         *
         * @param {Object} form - Form element
         * @returns {boolean}
         */
        run: function (form) {
            var formLength = form.elements.length,
                f,
                field,
                formvalid = true;

            // Loop all fields
            for (f = 0; f < formLength; f++) {
                field = form.elements[f];

                if (field.nodeName !== 'INPUT' && field.nodeName !== 'TEXTAREA' && field.nodeName !== 'SELECT') {
                    continue;
                }

                if (field.nodeName === 'INPUT') {
                    // Trim input values
                    field.value = field.value.trim();
                }

                if (validate(field) === false) {
                    formvalid = false;
                }
            }

            return formvalid;
        }
    };
} ());
<|endoftext|>


<commit_before>var ModalFormCtrl = function ($scope, $modalInstance, instance) {
    $scope.instance = instance;
    $scope.ok = function () {
        $modalInstance.close();
    };
};

admin_app.controller(
    'MainController',
    ['$scope', 'ModelService', function ($scope, ModelService) {
        // for site wide functions
        $scope.user = ModelService.user;
    }
]);

admin_app.controller(
    'ProjectListController',
    [
        '$scope',
        '$controller',
        '$modal',
        'ModelService',
        function ($scope, $controller, $modal, ModelService) {
            $scope.projects = ModelService.getProjects();

            $scope.$on('projects:updated', function () {
                $scope.projects = ModelService.getProjects();
            });

            $scope.init_form = function(instance) {
                var proposed_instance = angular.copy(instance);
                $scope.errors = [];

                // launch form modal
                var modalInstance = $modal.open({
                    templateUrl: MODAL_URLS.PROJECT,
                    controller: ModalFormCtrl,
                    resolve: {
                        instance: function() {
                            return proposed_instance;
                        }
                    }
                });
            };
        }
    ]
);

admin_app.controller(
    'ProjectDetailController',
    [
        '$scope',
        '$controller',
        '$state',
        '$stateParams',
        '$modal',
        'ModelService',
        function ($scope, $controller, $state, $stateParams, $modal, ModelService) {
            ModelService.setCurrentProjectById($stateParams.projectId);
            $scope.$on('current_project:updated', function () {
                $scope.current_project = ModelService.current_project;
            });
            $scope.$on('current_project:invalid', function () {
                // re-direct to 404
                $state.transitionTo('404');
            });
        }
    ]
);<commit_msg>don't GET user on load of ModelService<commit_after>var ModalFormCtrl = function ($scope, $modalInstance, instance) {
    $scope.instance = instance;
    $scope.ok = function () {
        $modalInstance.close();
    };
};

admin_app.controller(
    'MainController',
    ['$scope', 'ModelService', function ($scope, ModelService) {
        // for site wide functions
        $scope.user = ModelService.getUser();
    }
]);

admin_app.controller(
    'ProjectListController',
    [
        '$scope',
        '$controller',
        '$modal',
        'ModelService',
        function ($scope, $controller, $modal, ModelService) {
            $scope.projects = ModelService.getProjects();

            $scope.$on('projects:updated', function () {
                $scope.projects = ModelService.getProjects();
            });

            $scope.init_form = function(instance) {
                var proposed_instance = angular.copy(instance);
                $scope.errors = [];

                // launch form modal
                var modalInstance = $modal.open({
                    templateUrl: MODAL_URLS.PROJECT,
                    controller: ModalFormCtrl,
                    resolve: {
                        instance: function() {
                            return proposed_instance;
                        }
                    }
                });
            };
        }
    ]
);

admin_app.controller(
    'ProjectDetailController',
    [
        '$scope',
        '$controller',
        '$state',
        '$stateParams',
        '$modal',
        'ModelService',
        function ($scope, $controller, $state, $stateParams, $modal, ModelService) {
            ModelService.setCurrentProjectById($stateParams.projectId);
            $scope.$on('current_project:updated', function () {
                $scope.current_project = ModelService.current_project;
            });
            $scope.$on('current_project:invalid', function () {
                // re-direct to 404
                $state.transitionTo('404');
            });
        }
    ]
);<|endoftext|>


<commit_before>/**
 * Form validation
 */
bolt.validation = (function () {

    /**
     * Basic legacy validation checking
     * Adapted from  http://www.sitepoint.com/html5-forms-javascript-constraint-validation-api/
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function legacyValidation(field) {
        var
            valid = true,
            val = field.value,
            type = field.getAttribute('type'),
            chkbox = type === 'checkbox' || type === 'radio',
            required = field.getAttribute('required'),
            minlength = field.getAttribute('minlength'),
            maxlength = field.getAttribute('maxlength'),
            pattern = field.getAttribute('pattern');

        // Disabled fields should not be validated
        if (field.disabled) {
            return valid;
        }

        /* jshint -W126 */

        // value required?
        valid = valid && (!required ||
            (chkbox && field.checked) ||
            (!chkbox && val !== "")
        );

        // minlength or maxlength set?
        valid = valid && (chkbox || (
            (!minlength || val.length >= minlength) &&
            (!maxlength || val.length <= maxlength)
        ));

        /* jshint +W126 */

        // Test pattern
        if (valid && pattern) {
            pattern = new RegExp('^(?:' + pattern + ')$');
            valid = pattern.test(val);
        }

        return valid;
    }

    /**
     * Adds error classes to field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function addErrorClass(field, isCkeditor) {
        $(field).addClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).addClass('cke_error');
        }
    }

    /**
     * Removes error classes from field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function removeErrorClass(field, isCkeditor) {
        $(field).removeClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).removeClass('cke_error');
        }
    }

    /**
     * Show alertbox
     *
     * @param {string} id - Id of the alertbox
     * @param {string} msg - Message text
     */
    function showAlertbox(id, msg) {
        var alertbox = bolt.data.editcontent.error.alertbox.subst({
            '%NOTICE_ID%': id,
            '%MESSAGE%': msg
        });

        $(alertbox)
            .hide()
            .insertAfter('.page-header')
            .slideDown('fast');
    }

    /**
     * Validates a field
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function validate(field) {
        var hasNativeValidation,
            isCkeditor,
            task,
            value;

        var validates = $(field).data('validate');
        if (validates) {
            for (task in validates) {
                value = validates[task];

                switch (task) {
                    case 'float':
                        break;

                    case 'required':
                        break;

                    case 'min':
                        break;

                    case 'max':
                        break;

                    default:
                        console.log('UNKNOWN VALIDATION' + task + " -> " + value);
                }
            }
        } else {
            // Is native browser validation available?
            hasNativeValidation = typeof field.willValidate !== 'undefined';
            if (hasNativeValidation) {
                // Native validation available
                if (field.nodeName === 'INPUT' && field.type !== field.getAttribute('type')) {
                    // Input type not supported! Use legacy JavaScript validation
                    field.setCustomValidity(legacyValidation(field) ? '' : 'error');
                }
                // Native browser check
                field.checkValidity();
            } else {
                // Native validation not available
                field.validity = field.validity || {};
                // Set to result of validation function
                field.validity.valid = legacyValidation(field);

                // If "invalid" events are required, trigger it here
            }

            // Special validation for CKEditor fields
            isCkeditor = field.nodeName === 'TEXTAREA' && $(field).hasClass('ckeditor');
            if (isCkeditor) {
                var editor = CKEDITOR.instances[field.id],
                    error;

                if (editor) {
                    error = editor._.required === true && editor.getData().trim() === '';
                    if (hasNativeValidation) {
                        field.setCustomValidity(error ? 'Required' : '');
                    } else {
                        field.validity.valid = error;
                    }
                }
            }
        }

        var noticeID = 'notice--' + field.id;

        // First, remove any existing old notices
        $('#' + noticeID).remove();

        if (field.validity.valid) {
            removeErrorClass(field, isCkeditor);

            return true;
        } else {
            addErrorClass(field, isCkeditor);

            var msg = $(field).data('errortext');
            if (!msg) {
                msg = bolt.data.editcontent.error.msg.subst({'%FIELDNAME%': field.name});
            }
            showAlertbox(noticeID, msg);

            return false;
        }
    }

    return {
        /**
         * Validates all inputs of a form
         *
         * @param {Object} form - Form element
         * @returns {boolean}
         */
        run: function (form) {
            var formLength = form.elements.length,
                f,
                field,
                formvalid = true;

            // Loop all fields
            for (f = 0; f < formLength; f++) {
                field = form.elements[f];

                if (field.nodeName !== 'INPUT' && field.nodeName !== 'TEXTAREA' && field.nodeName !== 'SELECT') {
                    continue;
                }

                if (field.nodeName === 'INPUT') {
                    // Trim input values
                    field.value = field.value.trim();
                }

                if (validate(field) === false) {
                    formvalid = false;
                }
            }

            return formvalid;
        }
    };
} ());
<commit_msg>Add check for floats<commit_after>/**
 * Form validation
 */
bolt.validation = (function () {

    /**
     * Basic legacy validation checking
     * Adapted from  http://www.sitepoint.com/html5-forms-javascript-constraint-validation-api/
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function legacyValidation(field) {
        var
            valid = true,
            val = field.value,
            type = field.getAttribute('type'),
            chkbox = type === 'checkbox' || type === 'radio',
            required = field.getAttribute('required'),
            minlength = field.getAttribute('minlength'),
            maxlength = field.getAttribute('maxlength'),
            pattern = field.getAttribute('pattern');

        // Disabled fields should not be validated
        if (field.disabled) {
            return valid;
        }

        /* jshint -W126 */

        // value required?
        valid = valid && (!required ||
            (chkbox && field.checked) ||
            (!chkbox && val !== "")
        );

        // minlength or maxlength set?
        valid = valid && (chkbox || (
            (!minlength || val.length >= minlength) &&
            (!maxlength || val.length <= maxlength)
        ));

        /* jshint +W126 */

        // Test pattern
        if (valid && pattern) {
            pattern = new RegExp('^(?:' + pattern + ')$');
            valid = pattern.test(val);
        }

        return valid;
    }

    /**
     * Adds error classes to field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function addErrorClass(field, isCkeditor) {
        $(field).addClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).addClass('cke_error');
        }
    }

    /**
     * Removes error classes from field
     *
     * @param {Object} field - Field element
     * @param {boolean} isCkeditor - Is a isCkeditor field
     */
    function removeErrorClass(field, isCkeditor) {
        $(field).removeClass('error');

        if (isCkeditor) {
            $('#cke_' + field.id).removeClass('cke_error');
        }
    }

    /**
     * Show alertbox
     *
     * @param {string} id - Id of the alertbox
     * @param {string} msg - Message text
     */
    function showAlertbox(id, msg) {
        var alertbox = bolt.data.editcontent.error.alertbox.subst({
            '%NOTICE_ID%': id,
            '%MESSAGE%': msg
        });

        $(alertbox)
            .hide()
            .insertAfter('.page-header')
            .slideDown('fast');
    }

    /**
     * Validates a field
     *
     * @param {Object} field - Field element
     * @returns {boolean}
     */
    function validate(field) {
        var hasNativeValidation = typeof field.willValidate !== 'undefined',
            isCkeditor,
            task,
            param,
            value = field.value,
            error;

        var validates = $(field).data('validate');
        if (validates) {
            for (task in validates) {
                param = validates[task];

                switch (task) {
                    case 'float':
                        if (value !== '' && !value.match(/^[-+]?[0-9]*[,.]?[0-9]+([eE][-+]?[0-9]+)?$/)) {
                            error = bolt.data.validation.float;
                        }
                        break;

                    case 'required':
                        break;

                    case 'min':
                        break;

                    case 'max':
                        break;

                    default:
                        console.log('UNKNOWN VALIDATION' + task + " -> " + param);
                }
                // Stop on first error
                if (error) {
                    error = error.subst({'%FIELDNAME%': field.name});

                    if (hasNativeValidation) {
                        field.setCustomValidity(error);
                    } else {
                        field.validity.valid = false;
                    }
                    break;
                }
            }
        } else {
            // Is native browser validation available?
            if (hasNativeValidation) {
                // Native validation available
                if (field.nodeName === 'INPUT' && field.type !== field.getAttribute('type')) {
                    // Input type not supported! Use legacy JavaScript validation
                    field.setCustomValidity(legacyValidation(field) ? '' : 'error');
                }
                // Native browser check
                field.checkValidity();
            } else {
                // Native validation not available
                field.validity = field.validity || {};
                // Set to result of validation function
                field.validity.valid = legacyValidation(field);

                // If "invalid" events are required, trigger it here
            }

            // Special validation for CKEditor fields
            isCkeditor = field.nodeName === 'TEXTAREA' && $(field).hasClass('ckeditor');
            if (isCkeditor) {
                var editor = CKEDITOR.instances[field.id],
                    invalid;

                if (editor) {
                    invalid = editor._.required === true && editor.getData().trim() === '';
                    if (hasNativeValidation) {
                        field.setCustomValidity(invalid ? 'Required' : '');
                    } else {
                        field.validity.valid = !invalid;
                    }
                }
            }
        }

        var noticeID = 'notice--' + field.id;

        // First, remove any existing old notices
        $('#' + noticeID).remove();

        if (field.validity.valid) {
            removeErrorClass(field, isCkeditor);

            return true;
        } else {
            addErrorClass(field, isCkeditor);

            var msg = error || $(field).data('errortext');
            if (!msg) {
                msg = bolt.data.editcontent.error.msg.subst({'%FIELDNAME%': field.name});
            }
            showAlertbox(noticeID, msg);

            return false;
        }
    }

    return {
        /**
         * Validates all inputs of a form
         *
         * @param {Object} form - Form element
         * @returns {boolean}
         */
        run: function (form) {
            var formLength = form.elements.length,
                f,
                field,
                formvalid = true;

            // Loop all fields
            for (f = 0; f < formLength; f++) {
                field = form.elements[f];

                if (field.nodeName !== 'INPUT' && field.nodeName !== 'TEXTAREA' && field.nodeName !== 'SELECT') {
                    continue;
                }

                if (field.nodeName === 'INPUT') {
                    // Trim input values
                    field.value = field.value.trim();
                }

                if (validate(field) === false) {
                    formvalid = false;
                }
            }

            return formvalid;
        }
    };
} ());
<|endoftext|>