<commit_before>// http://james.padolsey.com/javascript/regex-selector-for-jquery/
jQuery.expr[':'].regex = function(elem, index, match) {
var matchParams = match[3].split(','),
    validLabels = /^(data|css):/,
    attr = {
        method: matchParams[0].match(validLabels) ?
                    matchParams[0].split(':')[0] : 'attr',
        property: matchParams.shift().replace(validLabels,'')
    },
    regexFlags = 'ig',
    regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
return regex.test(jQuery(elem)[attr.method](attr.property));
};
/**
 * Javascript-Equal-Height-Responsive-Rows
 * https://github.com/Sam152/Javascript-Equal-Height-Responsive-Rows
 */
(function($){$.fn.equalHeight=function(){var heights=[];$.each(this,function(i,element){$element=$(element);var element_height;var includePadding=($element.css('box-sizing')=='border-box')||($element.css('-moz-box-sizing')=='border-box');if(includePadding){element_height=$element.innerHeight();}else{element_height=$element.height();}
heights.push(element_height);});this.css('height',Math.max.apply(window,heights)+'px');return this;};$.fn.equalHeightGrid=function(columns){var $tiles=this;$tiles.css('height','auto');for(var i=0;i<$tiles.length;i++){if(i%columns===0){var row=$($tiles[i]);for(var n=1;n<columns;n++){row=row.add($tiles[i+n]);}
row.equalHeight();}}
return this;};$.fn.detectGridColumns=function(){var offset=0,cols=0;this.each(function(i,elem){var elem_offset=$(elem).offset().top;if(offset===0||elem_offset==offset){cols++;offset=elem_offset;}else{return false;}});return cols;};$.fn.responsiveEqualHeightGrid=function(){var _this=this;function syncHeights(){var cols=_this.detectGridColumns();_this.equalHeightGrid(cols);}
$(window).bind('resize load',syncHeights);syncHeights();return this;};})(jQuery);
// Scroll to caret position in a text field
function scrollToPosition($textarea, caret) {
    var text = $textarea.val();
    var textBeforePosition = text.substring(0, caret);
    $textarea.blur();
    $textarea.val(textBeforePosition);
    $textarea.focus();
    $textarea.val(text);
    $textarea[0].setSelectionRange(caret, caret);
};
// Posts presentation
$(document).ready(function() {
  // Ensure presentation is ok on DOM ready().
  $('.equal-divs').responsiveEqualHeightGrid();
  // Responsive images in posts
  $('.post-content img').load(function() {
      if ($(this).width() > 100) {
        $(this).addClass("img-responsive");
      }
  });
});
var x = setInterval(function() {
  // Ensure presentation is ok while media still loading.
  $('.equal-divs').responsiveEqualHeightGrid();
}, 500);
$(window).load(function() {
  // Stops presentation refresh when everything loaded.
  clearInterval(x);
});
// Ensure presentation is ok while spoiler animation is playing.
$(document).ready(function(){
  // Remove inner spoiler tags
  $(".panel-body .panel").remove();
  // Give spoiler tags unique ids and hyperlink adresses
  $("div[id^='spoiler-panel']").attr("id", function(index) {
    return 'spoiler-panel-' + (index+1);
  });
  $("a[href^='#spoiler-panel']").attr("href", function(index) {
    return '#spoiler-panel-' + (index+1);
  });
  $("a[href^='#spoiler-panel-']").click(function() {
    $spoiler = $(this);
    var spoiler_anim = setInterval(function() {
      $container = $spoiler.parents('.spoiler-container');
      $container.children("div[id^='spoiler-panel-']").on('shown.bs.collapse', function() {
        clearInterval(spoiler_anim);
      });
      $container.children("div[id^='spoiler-panel-']").on('hidden.bs.collapse', function() {
        clearInterval(spoiler_anim);
      });
      $row = $spoiler.parents('.row');
      $row.children('.equal-divs').responsiveEqualHeightGrid();
    }, 20);
  });
});
// socket.io
$(document).ready(function(){
  var socket = io('http://geekattitude.org:80');
  $(window).on('beforeunload', function(){
    socket.close();
  });
});
<commit_msg>Removed extra code<commit_after>// http://james.padolsey.com/javascript/regex-selector-for-jquery/
jQuery.expr[':'].regex = function(elem, index, match) {
var matchParams = match[3].split(','),
    validLabels = /^(data|css):/,
    attr = {
        method: matchParams[0].match(validLabels) ?
                    matchParams[0].split(':')[0] : 'attr',
        property: matchParams.shift().replace(validLabels,'')
    },
    regexFlags = 'ig',
    regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
return regex.test(jQuery(elem)[attr.method](attr.property));
};
/**
 * Javascript-Equal-Height-Responsive-Rows
 * https://github.com/Sam152/Javascript-Equal-Height-Responsive-Rows
 */
(function($){$.fn.equalHeight=function(){var heights=[];$.each(this,function(i,element){$element=$(element);var element_height;var includePadding=($element.css('box-sizing')=='border-box')||($element.css('-moz-box-sizing')=='border-box');if(includePadding){element_height=$element.innerHeight();}else{element_height=$element.height();}
heights.push(element_height);});this.css('height',Math.max.apply(window,heights)+'px');return this;};$.fn.equalHeightGrid=function(columns){var $tiles=this;$tiles.css('height','auto');for(var i=0;i<$tiles.length;i++){if(i%columns===0){var row=$($tiles[i]);for(var n=1;n<columns;n++){row=row.add($tiles[i+n]);}
row.equalHeight();}}
return this;};$.fn.detectGridColumns=function(){var offset=0,cols=0;this.each(function(i,elem){var elem_offset=$(elem).offset().top;if(offset===0||elem_offset==offset){cols++;offset=elem_offset;}else{return false;}});return cols;};$.fn.responsiveEqualHeightGrid=function(){var _this=this;function syncHeights(){var cols=_this.detectGridColumns();_this.equalHeightGrid(cols);}
$(window).bind('resize load',syncHeights);syncHeights();return this;};})(jQuery);
// Scroll to caret position in a text field
function scrollToPosition($textarea, caret) {
    var text = $textarea.val();
    var textBeforePosition = text.substring(0, caret);
    $textarea.blur();
    $textarea.val(textBeforePosition);
    $textarea.focus();
    $textarea.val(text);
    $textarea[0].setSelectionRange(caret, caret);
};
$(document).ready(function(){
  // Ensure presentation is ok on DOM ready()
  $('.equal-divs').responsiveEqualHeightGrid();
  // Ensure presentation is ok while media still loading
  var x = setInterval(function() {
    $('.equal-divs').responsiveEqualHeightGrid();
  }, 500);
  $(window).load(function() {
    // Stops presentation refresh when everything loaded
    clearInterval(x);
  });
  // Responsive images in posts
  $('.post-content img').load(function() {
      if ($(this).width() > 100) {
        $(this).addClass("img-responsive");
      }
  });
  // Remove inner spoiler tags
  $(".panel-body .panel").remove();
  // Ensure presentation is ok while spoiler animation is playing
  // Give spoiler tags unique ids and hyperlink adresses
  $("div[id^='spoiler-panel']").attr("id", function(index) {
    return 'spoiler-panel-' + (index+1);
  });
  $("a[href^='#spoiler-panel']").attr("href", function(index) {
    return '#spoiler-panel-' + (index+1);
  });
  $("a[href^='#spoiler-panel-']").click(function() {
    $spoiler = $(this);
    var spoiler_anim = setInterval(function() {
      $container = $spoiler.parents('.spoiler-container');
      $container.children("div[id^='spoiler-panel-']").on('shown.bs.collapse', function() {
        clearInterval(spoiler_anim);
      });
      $container.children("div[id^='spoiler-panel-']").on('hidden.bs.collapse', function() {
        clearInterval(spoiler_anim);
      });
      $row = $spoiler.parents('.row');
      $row.children('.equal-divs').responsiveEqualHeightGrid();
    }, 20);
  });
});
// socket.io
$(document).ready(function(){
  var socket = io('http://geekattitude.org:80');
  $(window).on('beforeunload', function(){
    socket.close();
  });
});
<|endoftext|>


<commit_before>d3.csv("dc.data.csv", function(csv){
	var data = crossfilter(csv);
	//set dimension vars
	var question_half_hour = data.dimension(function (d){
			//console.log(d.question_half_hour)
			return d.question_half_hour;
		}),
		question_weekday = data.dimension(function (d){
			//var day = d.question_weekday;
			//var name = ["Sunday", "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
			return d.question_weekday;
			//return day+"."+name[day];
		}),
		location_name = data.dimension(function (d){
			return d.location_name;
		}),
		patron_type = data.dimension(function(d){
			return d.patron_type;
		}),
		time_spent = data.dimension(function(d){
			return d.time_spent;
		});

	//set group vars
	var question_half_hour_group = question_half_hour.group().reduceCount(),
		question_weekday_group = question_weekday.group().reduceCount(),
		location_name_group = location_name.group().reduceCount(),
		patron_type_group = patron_type.group().reduceCount(),
		time_spent_group = time_spent.group().reduceCount();

	var question_half_hour_chart = dc.barChart("#question_half_hour")
		.width($("#question_half_hour").width())
		.height(300)
		.margins({top:10, left:50, right:10, bottom:80})
		.dimension(question_half_hour)
		.group(question_half_hour_group)
		.label(function(d){ return d.key; })
		.colors(["rgb(49, 130, 189)"])
		.elasticY(false)
		.x(d3.scale.ordinal().domain(question_half_hour_group))
        .xUnits(dc.units.ordinal)
        .yAxis().ticks(4);

	var question_weekday_chart = dc.rowChart("#question_weekday")
		.width(250)
		.height(250)
		.margins({top:10, left:10, right:10, bottom:30})
		.dimension(question_weekday)
		.group(question_weekday_group)
		.label(function(d){ return d.key; })
		.title(function(d){ return d.value; })
		.renderTitle(true)
		.colors(["rgb(65, 174, 118)"])
		.elasticX(true)
		.xAxis().ticks(4);

	var location_name_chart = dc.pieChart("#location_name")
		.dimension(location_name)
		.group(location_name_group)
		.radius([100])
		.innerRadius([50])
		.label(function(d){ return d.key; })
		.renderLabel(true)
		.colors(["#fdae61", "#ffffbf", "#abdda4", "#2b83ba", "#d7191c"])
		.legend(dc.legend().x(10).y(10).itemHeight(12).gap(5));

	var patron_type_chart = dc.rowChart("#patron_type")
		.width(250)
		.height(250)
		.margins({top:10, left:10, right:10, bottom:30})
		.dimension(patron_type)
		.group(patron_type_group)
		.label(function(d){ return d.key; })
		.title(function(d){ return d.value; })
		.colors(["rgb(240, 182, 76)"])
		.elasticX(true)
		.xAxis().ticks(4);

	var time_spent_chart = dc.rowChart("#time_spent")
		.width(250)
		.height(250)
		.margins({top:10, left:10, right:10, bottom:30})
		.dimension(time_spent)
		.group(time_spent_group)
		.label(function(d){ return d.key; })
		.title(function(d){ return d.value; })
		.colors(["rgb(242, 130, 110)"])
		.elasticX(true)
		.xAxis().ticks(4);

	dc.renderAll();

})
<commit_msg>j err<commit_after>d3.csv("dc.data.csv", function(csv){
	var data = crossfilter(csv);
	//set dimension vars
	var question_half_hour = data.dimension(function (d){
			//console.log(d.question_half_hour)
			return d.question_half_hour;
		}),
		question_weekday = data.dimension(function (d){
			//var day = d.question_weekday;
			//var name = ["Sunday", "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
			return d.question_weekday;
			//return day+"."+name[day];
		}),
		location_name = data.dimension(function (d){
			return d.location_name;
		}),
		patron_type = data.dimension(function(d){
			return d.patron_type;
		}),
		time_spent = data.dimension(function(d){
			return d.time_spent;
		});

	//set group vars
	var question_half_hour_group = question_half_hour.group().reduceCount(),
		question_weekday_group = question_weekday.group().reduceCount(),
		location_name_group = location_name.group().reduceCount(),
		patron_type_group = patron_type.group().reduceCount(),
		time_spent_group = time_spent.group().reduceCount();

	var question_half_hour_chart = dc.barChart("#question_half_hour")
		.width($("#question_half_hour").width())
		.height(300)
		.margins({top:10, left:50, right:10, bottom:80})
		.dimension(question_half_hour)
		.group(question_half_hour_group)
		.label(function(d){ return d.key; })
		.colors(["rgb(49, 130, 189)"])
		.elasticY(false)
		.x(d3.scale.ordinal().domain(question_half_hour_group))
        .xUnits(dc.units.ordinal)
        .yAxis().ticks(4);

	var question_weekday_chart = dc.rowChart("#question_weekday")
		.width(250)
		.height(250)
		.margins({top:10, left:10, right:10, bottom:30})
		.dimension(question_weekday)
		.group(question_weekday_group)
		.label(function(d){ return d.key; })
		.title(function(d){ return d.value; })
		.renderTitle(true)
		.colors(["rgb(65, 174, 118)"])
		.elasticX(true)
		.xAxis().ticks(4);

	var location_name_chart = dc.pieChart("#location_name")
		.dimension(location_name)
		.group(location_name_group)
		.radius([100])
		.innerRadius([50])
		.label(function(d){ return d.key; })
		.colors(["#fdae61", "#ffffbf", "#abdda4", "#2b83ba", "#d7191c"])
		.legend(dc.legend().x(10).y(10).itemHeight(12).gap(5));

	var patron_type_chart = dc.rowChart("#patron_type")
		.width(250)
		.height(250)
		.margins({top:10, left:10, right:10, bottom:30})
		.dimension(patron_type)
		.group(patron_type_group)
		.label(function(d){ return d.key; })
		.title(function(d){ return d.value; })
		.colors(["rgb(240, 182, 76)"])
		.elasticX(true)
		.xAxis().ticks(4);

	var time_spent_chart = dc.rowChart("#time_spent")
		.width(250)
		.height(250)
		.margins({top:10, left:10, right:10, bottom:30})
		.dimension(time_spent)
		.group(time_spent_group)
		.label(function(d){ return d.key; })
		.title(function(d){ return d.value; })
		.colors(["rgb(242, 130, 110)"])
		.elasticX(true)
		.xAxis().ticks(4);

	dc.renderAll();

})
<|endoftext|>


<commit_before>require('../../../support/test_helper');

var assert        = require('../../../support/assert');
var TestClient = require('../../../support/test-client');

describe('widgets', function() {

    describe('histograms', function() {

        afterEach(function(done) {
            if (this.testClient) {
                this.testClient.drain(done);
            } else {
                done();
            }
        });

        function histogramsMapConfig(widgets) {
            return {
                version: '1.5.0',
                layers: [
                    {
                        type: 'mapnik',
                        options: {
                            sql: 'select * from populated_places_simple_reduced',
                            cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
                            cartocss_version: '2.0.1',
                            widgets: widgets || {
                                scalerank: {
                                    type: 'histogram',
                                    options: {
                                        column: 'scalerank'
                                    }
                                },
                                pop_max: {
                                    type: 'histogram',
                                    options: {
                                        column: 'pop_max'
                                    }
                                }
                            }
                        }
                    }
                ]
            };
        }

        it('can be fetched from a valid histogram', function(done) {
            this.testClient = new TestClient(histogramsMapConfig());
            this.testClient.getWidget('scalerank', function (err, res, histogram) {
                assert.ok(!err, err);
                assert.ok(histogram);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);

                assert.deepEqual(histogram.bins[0], { bin: 0, freq: 179, min: 1, max: 1, avg: 1 });

                done();
            });
        });

        it('can be fetched from a valid histogram', function(done) {
            this.testClient = new TestClient(histogramsMapConfig());
            this.testClient.getWidget('pop_max', function (err, res, histogram) {
                assert.ok(!err, err);
                assert.ok(histogram);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);

                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 47, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
                );

                done();
            });
        });

        it('can be fetched from a valid filtered histogram', function(done) {
            this.testClient = new TestClient(histogramsMapConfig());
            var popMaxFilter = {
                pop_max: {
                    min: 1e5,
                    max: 1e7
                }
            };
            var params = {
                own_filter: 1,
                filters: {
                    layers: [popMaxFilter]
                }
            };
            this.testClient.getWidget('pop_max', params, function (err, res, histogram) {
                assert.ok(!err, err);
                assert.ok(histogram);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);

                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 7, min: 8829000, max: 9904000, avg: 9340914.714285715, freq: 7 }
                );

                done();
            });
        });

        it('returns array with freq=0 entries for empty bins', function(done) {
            var histogram20binsMapConfig = {
                version: '1.5.0',
                layers: [
                    {
                        type: 'mapnik',
                        options: {
                            sql: 'select * from populated_places_simple_reduced',
                            cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
                            cartocss_version: '2.0.1',
                            widgets: {
                                pop_max: {
                                    type: 'histogram',
                                    options: {
                                        column: 'pop_max'
                                    }
                                }
                            }
                        }
                    }
                ]
            };

            this.testClient = new TestClient(histogram20binsMapConfig);
            this.testClient.getWidget('pop_max', { start: 0, end: 35676000, bins: 20 }, function (err, res, histogram) {
                assert.ok(!err, err);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);
                assert.ok(histogram.bins.length);
                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 19, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
                );

                var emptyBin = histogram.bins[18];
                assert.ok(!emptyBin);

                done();
            });
        });

        it('can use a fixed number of bins', function(done) {
            var fixedBinsHistogramMapConfig = histogramsMapConfig({
                pop_max: {
                    type: 'histogram',
                    options: {
                        column: 'pop_max'
                    }
                }
            });

            this.testClient = new TestClient(fixedBinsHistogramMapConfig);
            this.testClient.getWidget('pop_max', { bins: 5 }, function (err, res, histogram) {
                assert.ok(!err, err);
                assert.equal(histogram.type, 'histogram');

                assert.equal(histogram.bins_count, 5);

                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);
                assert.deepEqual(
                    histogram.bins[0],
                    { bin: 0, min: 0, max: 7067423, avg: 280820.0057731959, freq: 7275 }
                );
                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 4, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
                );

                done();
            });
        });

        function validateHistogramBins(histogram) {
            var binWidth = histogram.bin_width;
            var start = histogram.bins_start;
            var end = start + (histogram.bins_count * binWidth);

            var firstBin = histogram.bins[0];
            assert.equal(firstBin.min, start,
                'First bin does not match min and start ' + JSON.stringify({
                    min: firstBin.min,
                    start: start
                })
            );

            var lastBin = histogram.bins[histogram.bins.length - 1];
            assert.equal(lastBin.max, end,
                'Last bin does not match max and end ' + JSON.stringify({
                    max: lastBin.max,
                    end: end
                })
            );

            function getBinStartEnd(binIndex) {
                return {
                    start: start + (binIndex * binWidth),
                    end: start + ((binIndex + 1) * binWidth)
                };
            }

            histogram.bins.forEach(function(bin) {
                var binStartEnd = getBinStartEnd(bin.bin);

                assert.ok(binStartEnd.start <= bin.min,
                    'Bin start bigger than bin min ' + JSON.stringify({
                        bin: bin.bin,
                        min: bin.min,
                        start: binStartEnd.start
                    })
                );

                assert.ok(binStartEnd.end >= bin.max,
                    'Bin end smaller than bin max ' + JSON.stringify({
                        bin: bin.bin,
                        max: bin.max,
                        end: binStartEnd.end
                    })
                );

                assert.ok(bin.avg >= bin.min && bin.avg <= bin.max,
                        'Bin avg not between min and max values' + JSON.stringify({
                        bin: bin.bin,
                        avg: bin.avg,
                        min: bin.min,
                        max: bin.max
                    })
                );
            });
        }

        describe('datetime column', function() {
            afterEach(function(done) {
                if (this.testClient) {
                    this.testClient.drain(done);
                } else {
                    done();
                }
            });

            var updatedAtFilter = {
                updated_at: {
                    min: 0
                }
            };

            it('can use a datetime column', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                this.testClient.getWidget('updated_at', function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.ok(histogram.bins.length);

                    done();
                });
            });

            it('can use a datetime filtered column', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [updatedAtFilter]
                    }
                };
                this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.ok(histogram.bins.length);

                    done();
                });
            });

            it('can getTile with datetime filtered column', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [updatedAtFilter]
                    }
                };
                this.testClient.getTile(0, 0, 0, params, function (err, res, tile) {
                    assert.ok(!err, err);
                    assert.ok(tile);

                    done();
                });
            });

            it('can use two columns with different types', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    },
                    pop_max: {
                        type: 'histogram',
                        options: {
                            column: 'pop_max'
                        }
                    }
                }));

                var popMaxFilter = {
                    pop_max: {
                        max: 1e7
                    }
                };

                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [popMaxFilter]
                    }
                };

                this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.ok(histogram.bins.length);

                    done();
                });
            });
        });

    });

});
<commit_msg>Test for #606: function avg(timestamp with time zone) does not exist<commit_after>require('../../../support/test_helper');

var assert        = require('../../../support/assert');
var TestClient = require('../../../support/test-client');

describe('widgets', function() {

    describe('histograms', function() {

        afterEach(function(done) {
            if (this.testClient) {
                this.testClient.drain(done);
            } else {
                done();
            }
        });

        function histogramsMapConfig(widgets) {
            return {
                version: '1.5.0',
                layers: [
                    {
                        type: 'mapnik',
                        options: {
                            sql: 'select * from populated_places_simple_reduced',
                            cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
                            cartocss_version: '2.0.1',
                            widgets: widgets || {
                                scalerank: {
                                    type: 'histogram',
                                    options: {
                                        column: 'scalerank'
                                    }
                                },
                                pop_max: {
                                    type: 'histogram',
                                    options: {
                                        column: 'pop_max'
                                    }
                                }
                            }
                        }
                    }
                ]
            };
        }

        it('can be fetched from a valid histogram', function(done) {
            this.testClient = new TestClient(histogramsMapConfig());
            this.testClient.getWidget('scalerank', function (err, res, histogram) {
                assert.ok(!err, err);
                assert.ok(histogram);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);

                assert.deepEqual(histogram.bins[0], { bin: 0, freq: 179, min: 1, max: 1, avg: 1 });

                done();
            });
        });

        it('can be fetched from a valid histogram', function(done) {
            this.testClient = new TestClient(histogramsMapConfig());
            this.testClient.getWidget('pop_max', function (err, res, histogram) {
                assert.ok(!err, err);
                assert.ok(histogram);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);

                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 47, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
                );

                done();
            });
        });

        it('can be fetched from a valid filtered histogram', function(done) {
            this.testClient = new TestClient(histogramsMapConfig());
            var popMaxFilter = {
                pop_max: {
                    min: 1e5,
                    max: 1e7
                }
            };
            var params = {
                own_filter: 1,
                filters: {
                    layers: [popMaxFilter]
                }
            };
            this.testClient.getWidget('pop_max', params, function (err, res, histogram) {
                assert.ok(!err, err);
                assert.ok(histogram);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);

                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 7, min: 8829000, max: 9904000, avg: 9340914.714285715, freq: 7 }
                );

                done();
            });
        });

        it('returns array with freq=0 entries for empty bins', function(done) {
            var histogram20binsMapConfig = {
                version: '1.5.0',
                layers: [
                    {
                        type: 'mapnik',
                        options: {
                            sql: 'select * from populated_places_simple_reduced',
                            cartocss: '#layer0 { marker-fill: red; marker-width: 10; }',
                            cartocss_version: '2.0.1',
                            widgets: {
                                pop_max: {
                                    type: 'histogram',
                                    options: {
                                        column: 'pop_max'
                                    }
                                }
                            }
                        }
                    }
                ]
            };

            this.testClient = new TestClient(histogram20binsMapConfig);
            this.testClient.getWidget('pop_max', { start: 0, end: 35676000, bins: 20 }, function (err, res, histogram) {
                assert.ok(!err, err);
                assert.equal(histogram.type, 'histogram');
                validateHistogramBins(histogram);
                assert.ok(histogram.bins.length);
                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 19, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
                );

                var emptyBin = histogram.bins[18];
                assert.ok(!emptyBin);

                done();
            });
        });

        it('can use a fixed number of bins', function(done) {
            var fixedBinsHistogramMapConfig = histogramsMapConfig({
                pop_max: {
                    type: 'histogram',
                    options: {
                        column: 'pop_max'
                    }
                }
            });

            this.testClient = new TestClient(fixedBinsHistogramMapConfig);
            this.testClient.getWidget('pop_max', { bins: 5 }, function (err, res, histogram) {
                assert.ok(!err, err);
                assert.equal(histogram.type, 'histogram');

                assert.equal(histogram.bins_count, 5);

                validateHistogramBins(histogram);

                assert.ok(histogram.bins.length);
                assert.deepEqual(
                    histogram.bins[0],
                    { bin: 0, min: 0, max: 7067423, avg: 280820.0057731959, freq: 7275 }
                );
                assert.deepEqual(
                    histogram.bins[histogram.bins.length - 1],
                    { bin: 4, freq: 1, min: 35676000, max: 35676000, avg: 35676000 }
                );

                done();
            });
        });

        function validateHistogramBins(histogram) {
            var binWidth = histogram.bin_width;
            var start = histogram.bins_start;
            var end = start + (histogram.bins_count * binWidth);

            var firstBin = histogram.bins[0];
            assert.equal(firstBin.min, start,
                'First bin does not match min and start ' + JSON.stringify({
                    min: firstBin.min,
                    start: start
                })
            );

            var lastBin = histogram.bins[histogram.bins.length - 1];
            assert.equal(lastBin.max, end,
                'Last bin does not match max and end ' + JSON.stringify({
                    max: lastBin.max,
                    end: end
                })
            );

            function getBinStartEnd(binIndex) {
                return {
                    start: start + (binIndex * binWidth),
                    end: start + ((binIndex + 1) * binWidth)
                };
            }

            histogram.bins.forEach(function(bin) {
                var binStartEnd = getBinStartEnd(bin.bin);

                assert.ok(binStartEnd.start <= bin.min,
                    'Bin start bigger than bin min ' + JSON.stringify({
                        bin: bin.bin,
                        min: bin.min,
                        start: binStartEnd.start
                    })
                );

                assert.ok(binStartEnd.end >= bin.max,
                    'Bin end smaller than bin max ' + JSON.stringify({
                        bin: bin.bin,
                        max: bin.max,
                        end: binStartEnd.end
                    })
                );

                assert.ok(bin.avg >= bin.min && bin.avg <= bin.max,
                        'Bin avg not between min and max values' + JSON.stringify({
                        bin: bin.bin,
                        avg: bin.avg,
                        min: bin.min,
                        max: bin.max
                    })
                );
            });
        }

        describe('datetime column', function() {
            afterEach(function(done) {
                if (this.testClient) {
                    this.testClient.drain(done);
                } else {
                    done();
                }
            });

            var updatedAtFilter = {
                updated_at: {
                    min: 0
                }
            };

            it('can use a datetime column', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                this.testClient.getWidget('updated_at', function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.ok(histogram.bins.length);

                    done();
                });
            });

            it('can use a datetime filtered column', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [updatedAtFilter]
                    }
                };
                this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.ok(histogram.bins.length);

                    done();
                });
            });

            it('can use a datetime filtered column with no results', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [{
                            updated_at: {
                                // this will remove all results
                                max: -1
                            }
                        }]
                    }
                };
                this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.equal(histogram.bins.length, 0);

                    done();
                });
            });

            it('can getTile with datetime filtered column', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    }
                }));
                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [updatedAtFilter]
                    }
                };
                this.testClient.getTile(0, 0, 0, params, function (err, res, tile) {
                    assert.ok(!err, err);
                    assert.ok(tile);

                    done();
                });
            });

            it('can use two columns with different types', function(done) {
                this.testClient = new TestClient(histogramsMapConfig({
                    updated_at: {
                        type: 'histogram',
                        options: {
                            column: 'updated_at'
                        }
                    },
                    pop_max: {
                        type: 'histogram',
                        options: {
                            column: 'pop_max'
                        }
                    }
                }));

                var popMaxFilter = {
                    pop_max: {
                        max: 1e7
                    }
                };

                var params = {
                    own_filter: 1,
                    filters: {
                        layers: [popMaxFilter]
                    }
                };

                this.testClient.getWidget('updated_at', params, function (err, res, histogram) {
                    assert.ok(!err, err);
                    assert.ok(histogram);
                    assert.equal(histogram.type, 'histogram');

                    assert.ok(histogram.bins.length);

                    done();
                });
            });
        });

    });

});
<|endoftext|>


<commit_before>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CourseTitle2");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CourseTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    /*Teacher*/
    gvm.availableTeacher = ko.observableArray([]);
    gvm.currentteacherid = null;
    /*teacher*/

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);

        // Attach delete handler to delete button
        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });

        // Attach edit handler to edit button
        $('#editbtn-' + id).bind('click', function(event, data){
            // Edit the table item
            showEditProjectTypeModal(code, name, desc, id);
            event.stopPropagation();
        });

        //Attach manage handler to manage competences, subcompetences and indicators to manage button
        $('#managebtn-' + id).bind('click', function(event, data) {
            //TODO
        });

        /*$('#studentbtn-' + id).bind('click', function(event, data) {
            showCoupleStudentListModal(id);
            gvm.currentprojectid = id;
            gvm.currentselectedlist = -1;
            event.stopPropagation();
            loadCoupleDropdown();
        });*/
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

    gvm.updateDropdowns = function() {
        $.getJSON('api/lastdropdownchoice/' + gvm.userId, function(data) {
            if(!$.isEmptyObject(data)) {
                $.each(data, function(i, item) {
                    $(".btn-teacher span:first").text(item.teacher);
                    gvm.currentteacherid = item.id;
                    gvm.updateTeacher(item.username);
                });
            } else {

            }
        });
    }

    gvm.updateTeacher = function(id) {
    $.getJSON('/api/teacherrapport/' + id, function(data) {
        gvm.availableTeacher.removeAll();
        $.each(data, function(i, item) {
            gvm.availableTeacher.push(item);
                console.log(item)
            /* Add listener to listitem */
            $("#teacherbtn-" + item.id).click(function(){
                $(".btn-teacher span:first").text($(this).text());
                gvm.currentteacherid = item.id;
                loadTablePage(item.id, 1);
            });
        });
    });
    }
    }
/*
 * Delete item from table given the id.
 */
function deleteTableItem(id, tblOject) {
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen? \r\n Let op: verwijderde items blijven in het systeem en kunnen weer actief gezet worden door een administrator. \r\n Gelieve de administrator te contacteren om een vak definitief te verwijderen.", function(val){
        if(val){
            $.ajax({
                url: "/api/coursedelete/" + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblOject);
                }
            });
        }
    });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeForm(serialData, callback) {
    $.ajax({
            url: "/api/courserapport",
            type: "POST",
            data: serialData,
            success: function(data) {
                viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
                callback(true);
            },
            error: function(data) {
                callback(false);
            }
        });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeRaw(code, name, description, callback) {
    addNewProjecttypeForm("code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Update the projecttype
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeForm(id, serialData, callback) {
    $.ajax({
        url: "/api/courseupdate/" + id,
        type: "PUT",
        data: serialData,
        success: function(data) {
            //viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
            loadTablePage(1); //TODO now it is refreshing table after updating but it redirects to pagenr 1     WERKT NIET
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

/**
 * update project type
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeRaw(id, code, name, description, callback) {
    updateProjecttypeForm(id, "code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Load page of the table
 */
function loadTablePage(pagenr)
{
    $.getJSON('/api/coursesrapport/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });

}

/**
 * Show a new projecttype modal.
 * @returns {undefined}
 */
function showNewProjectTypeModal()
{
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("AddNewCourse"));
    setGeneralModalBody('<form id="newprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description"> \

 \

' +
                '<button class="btn btn-wide btn-default btn-teacher dropdown-toggle" type="button" id="availableTeacher" data-toggle="dropdown" aria-expanded="true" placeholder="' + i18n.__('TeacherTableTitle') + '">' +
                    'Teacher' + '' +
                '</button>' +
                '
' +
                    '

' +
                '
' +
            '
' +
            '</form>' );

    addGeneralModalButton(i18n.__("AddBtn"), function(){
        console.log($('#newprojectform').serialize());
       addNewProjecttypeForm($('#newprojectform').serialize(), function(result){
            hideModal();
        });
    });

    showGeneralModal();
}

/**
 * Show the edit projecttype modal.
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} tid
 * @returns {undefined}
 */
function showEditProjectTypeModal(code, name, description, tid)
{
  resetGeneralModal();
    setGeneralModalTitle(i18n.__("EditProjectTitle2"));
    setGeneralModalBody('<form id="updateprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code" value="' + code + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name" value="' + name + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description" value="' + description + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateProjecttypeForm(tid, $('#updateprojectform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function showCoupleStudentListModal(projectid) {
    viewModel.currentselectedlist = -1;
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("CoupleStudentList"));
    setGeneralModalBody(
        '
' +
            '<button class="btn btn-default dropdown-toggle" type="button" id="dropdownStudLists" data-toggle="dropdown" aria-expanded="true">' +
                'Dropdown' +
                '' +
            '</button>' +
            '
' +
            '
' +
        '
');

    addGeneralModalButton(i18n.__("SaveBtn"), function() {
        updateListForm(viewModel.currentselectedlist, $('#coupleform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })
    showGeneralModal();
}
function loadCoupleDropdown() {
    $.getJSON('/api/studentlists/' + viewModel.userId, function(data) {
        $.each(data, function(i, item) {
            $("#ddlLists").append('
' + item.name + '
')
            $("#dropdownitem-" + item.id).click(function(){
                $(this).parent().parent().parent().removeClass("open");
                $(this).parent().parent().parent().find(".btn").html($(this).text() + '');
                viewModel.currentselectedlist = item.id;
            });
        });
    });
    $("#dropdownStudLists").click(function() {
        $(this).parent().toggleClass("open");
    });
}

function updateListForm(id, serialData, callback) {
    $.ajax({
        url: "/api/project/" + viewModel.currentprojectid + "/studentlist/" + id,
        type: "POST",
        data: serialData,
        success: function(data) {
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function initPage() {
    // Add button handlers
    $('#addProjectTypeBtn').click(function(){
        showNewProjectTypeModal();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.updateDropdowns();
    });

    loadTablePage(1);
}
<commit_msg>coursesrapportenviewmodel teacher<commit_after>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CourseTitle2");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CourseTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    /*Teacher*/
    gvm.availableTeacher = ko.observableArray([]);
    gvm.currentteacherid = null;
    /*teacher*/

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);

        // Attach delete handler to delete button
        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });

        // Attach edit handler to edit button
        $('#editbtn-' + id).bind('click', function(event, data){
            // Edit the table item
            showEditProjectTypeModal(code, name, desc, id);
            event.stopPropagation();
        });

        //Attach manage handler to manage competences, subcompetences and indicators to manage button
        $('#managebtn-' + id).bind('click', function(event, data) {
            //TODO
        });

        /*$('#studentbtn-' + id).bind('click', function(event, data) {
            showCoupleStudentListModal(id);
            gvm.currentprojectid = id;
            gvm.currentselectedlist = -1;
            event.stopPropagation();
            loadCoupleDropdown();
        });*/
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

    gvm.updateDropdowns = function() {
        $.getJSON('api/lastdropdownchoice/' + gvm.userId, function(data) {
            if(!$.isEmptyObject(data)) {
                $.each(data, function(i, item) {
                    $(".btn-teacher span:first").text(item.teacher);
                    gvm.currentteacherid = item.id;
                    gvm.updateTeacher(item.username);
                });
            } else {

            }
        });
    }

    gvm.updateTeacher = function(id) {
    $.getJSON('/api/teacherrapport/' + id, function(data) {
        gvm.availableTeacher.removeAll();
        $.each(data, function(i, item) {
            gvm.availableTeacher.push(item);
                console.log(item);
            /* Add listener to listitem */
            $("#teacherbtn-" + item.id).click(function(){
                $(".btn-teacher span:first").text($(this).text());
                gvm.currentteacherid = item.id;
                loadTablePage(item.id, 1);
            });
        });
    });
    }
    }
/*
 * Delete item from table given the id.
 */
function deleteTableItem(id, tblOject) {
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen? \r\n Let op: verwijderde items blijven in het systeem en kunnen weer actief gezet worden door een administrator. \r\n Gelieve de administrator te contacteren om een vak definitief te verwijderen.", function(val){
        if(val){
            $.ajax({
                url: "/api/coursedelete/" + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblOject);
                }
            });
        }
    });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeForm(serialData, callback) {
    $.ajax({
            url: "/api/courserapport",
            type: "POST",
            data: serialData,
            success: function(data) {
                viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
                callback(true);
            },
            error: function(data) {
                callback(false);
            }
        });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeRaw(code, name, description, callback) {
    addNewProjecttypeForm("code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Update the projecttype
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeForm(id, serialData, callback) {
    $.ajax({
        url: "/api/courseupdate/" + id,
        type: "PUT",
        data: serialData,
        success: function(data) {
            //viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
            loadTablePage(1); //TODO now it is refreshing table after updating but it redirects to pagenr 1     WERKT NIET
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

/**
 * update project type
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeRaw(id, code, name, description, callback) {
    updateProjecttypeForm(id, "code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Load page of the table
 */
function loadTablePage(pagenr)
{
    $.getJSON('/api/coursesrapport/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });

}

/**
 * Show a new projecttype modal.
 * @returns {undefined}
 */
function showNewProjectTypeModal()
{
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("AddNewCourse"));
    setGeneralModalBody('<form id="newprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description"> \

 \

' +
                '<button class="btn btn-wide btn-default btn-teacher dropdown-toggle" type="button" id="availableTeacher" data-toggle="dropdown" aria-expanded="true" placeholder="' + i18n.__('TeacherTableTitle') + '">' +
                    'Teacher' + '' +
                '</button>' +
                '
' +
                    '

' +
                '
' +
            '
' +
            '</form>' );

    addGeneralModalButton(i18n.__("AddBtn"), function(){
        console.log($('#newprojectform').serialize());
       addNewProjecttypeForm($('#newprojectform').serialize(), function(result){
            hideModal();
        });
    });

    showGeneralModal();
}

/**
 * Show the edit projecttype modal.
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} tid
 * @returns {undefined}
 */
function showEditProjectTypeModal(code, name, description, tid)
{
  resetGeneralModal();
    setGeneralModalTitle(i18n.__("EditProjectTitle2"));
    setGeneralModalBody('<form id="updateprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code" value="' + code + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name" value="' + name + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description" value="' + description + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateProjecttypeForm(tid, $('#updateprojectform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function showCoupleStudentListModal(projectid) {
    viewModel.currentselectedlist = -1;
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("CoupleStudentList"));
    setGeneralModalBody(
        '
' +
            '<button class="btn btn-default dropdown-toggle" type="button" id="dropdownStudLists" data-toggle="dropdown" aria-expanded="true">' +
                'Dropdown' +
                '' +
            '</button>' +
            '
' +
            '
' +
        '
');

    addGeneralModalButton(i18n.__("SaveBtn"), function() {
        updateListForm(viewModel.currentselectedlist, $('#coupleform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })
    showGeneralModal();
}
function loadCoupleDropdown() {
    $.getJSON('/api/studentlists/' + viewModel.userId, function(data) {
        $.each(data, function(i, item) {
            $("#ddlLists").append('
' + item.name + '
')
            $("#dropdownitem-" + item.id).click(function(){
                $(this).parent().parent().parent().removeClass("open");
                $(this).parent().parent().parent().find(".btn").html($(this).text() + '');
                viewModel.currentselectedlist = item.id;
            });
        });
    });
    $("#dropdownStudLists").click(function() {
        $(this).parent().toggleClass("open");
    });
}

function updateListForm(id, serialData, callback) {
    $.ajax({
        url: "/api/project/" + viewModel.currentprojectid + "/studentlist/" + id,
        type: "POST",
        data: serialData,
        success: function(data) {
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function initPage() {
    // Add button handlers
    $('#addProjectTypeBtn').click(function(){
        showNewProjectTypeModal();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.updateDropdowns();
    });

    loadTablePage(1);
}
<|endoftext|>


<commit_before>// @flow
/* eslint-disable flowtype/require-return-type */

import {
  CLEAN_NEW_DISK_DIALOG_SUBTREE,
  SET_NEW_DISK_DIALOG_PROGRESS_INDICATOR,
  SET_NEW_DISK_DIALOG_ERROR_TEXT,
  SET_NEW_DISK_DIALOG_DONE,
} from '_/constants'

export function cleanNewDiskDialogSubtree () {
  return {
    type: CLEAN_NEW_DISK_DIALOG_SUBTREE,
  }
}

export function setNewDiskDialogProgressIndicator (visible: boolean) {
  return {
    type: SET_NEW_DISK_DIALOG_PROGRESS_INDICATOR,
    payload: { visible },
  }
}

export function setNewDiskDialogErrorText (errorText: boolean) {
  return {
    type: SET_NEW_DISK_DIALOG_ERROR_TEXT,
    payload: { errorText },
  }
}

export function setNewDiskDialogDone () {
  return {
    type: SET_NEW_DISK_DIALOG_DONE,
  }
}
<commit_msg>Fix a broken constants.js import<commit_after>// @flow
/* eslint-disable flowtype/require-return-type */

import {
  CLEAN_NEW_DISK_DIALOG_SUBTREE,
  SET_NEW_DISK_DIALOG_PROGRESS_INDICATOR,
  SET_NEW_DISK_DIALOG_ERROR_TEXT,
  SET_NEW_DISK_DIALOG_DONE,
} from './constants'

export function cleanNewDiskDialogSubtree () {
  return {
    type: CLEAN_NEW_DISK_DIALOG_SUBTREE,
  }
}

export function setNewDiskDialogProgressIndicator (visible: boolean) {
  return {
    type: SET_NEW_DISK_DIALOG_PROGRESS_INDICATOR,
    payload: { visible },
  }
}

export function setNewDiskDialogErrorText (errorText: boolean) {
  return {
    type: SET_NEW_DISK_DIALOG_ERROR_TEXT,
    payload: { errorText },
  }
}

export function setNewDiskDialogDone () {
  return {
    type: SET_NEW_DISK_DIALOG_DONE,
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import { storiesOf } from '@storybook/react';
import { text, select, boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import { State, Store } from '@sambego/storybook-state';
import OptionsHelper from '../../utils/helpers/options-helper';
import notes from './documentation/notes.md';
import Dialog from './dialog';
import Button from '../button/button';
import DialogStyledComponents from './dialog.component';

const store = new Store({
  open: false
});

const handleCancel = (evt) => {
  store.set({ open: false });
  action('cancel')(evt);
};

const handleOpen = (evt) => {
  store.set({ open: true });
  action('open')(evt);
};

const handleClick = (evt) => {
  action('click')(evt);
};

storiesOf('Dialog', module)
  .addParameters({
    info: {
      propTablesExclude: [Button, State]
    }
  })
  .add('styled component', () => {
    const height = text('height', '400');
    const title = text('title', 'Example Dialog');
    const subtitle = text('subtitle', 'Example Subtitle');
    const size = select('size', OptionsHelper.sizesRestricted, Dialog.defaultProps.size);
    const showCloseIcon = boolean('showCloseIcon', Dialog.defaultProps.showCloseIcon);
    const autoFocus = boolean('autoFocus', Dialog.defaultProps.autoFocus);
    const stickyFormFooter = boolean('stickyFormFooter', false);
    const enableBackgroundUI = boolean('enableBackgroundUI', false);
    const disableEscKey = boolean('disableEscKey', false);
    const ariaRole = text('ariaRole', Dialog.defaultProps.ariaRole);

    return (

        <Button onClick={ handleOpen }>Open Preview</Button>
        <State store={ store }>
          <DialogStyledComponents
            open={ store.get('open') }
            onCancel={ handleCancel }
            height={ height }
            title={ title }
            subtitle={ subtitle }
            size={ size }
            showCloseIcon={ showCloseIcon }
            autoFocus={ autoFocus }
            stickyFormFooter={ stickyFormFooter }
            enableBackgroundUI={ enableBackgroundUI }
            disableEscKey={ disableEscKey }
            ariaRole={ ariaRole }
            onClick={ handleClick }
          />
        </State>

    );
  })
  .add('default', () => {
    const height = text('height', '400');
    const title = text('title', 'Example Dialog');
    const subtitle = text('subtitle', 'Example Subtitle');
    const size = select('size', OptionsHelper.sizesRestricted, Dialog.defaultProps.size);
    const showCloseIcon = boolean('showCloseIcon', Dialog.defaultProps.showCloseIcon);
    const autoFocus = boolean('autoFocus', Dialog.defaultProps.autoFocus);
    const stickyFormFooter = boolean('stickyFormFooter', false);
    const enableBackgroundUI = boolean('enableBackgroundUI', false);
    const disableEscKey = boolean('disableEscKey', false);
    const ariaRole = text('ariaRole', Dialog.defaultProps.ariaRole);

    return (

        <Button onClick={ handleOpen }>Open Preview</Button>
        <State store={ store }>
          <Dialog
            open={ store.get('open') }
            onCancel={ handleCancel }
            height={ height }
            title={ title }
            subtitle={ subtitle }
            size={ size }
            showCloseIcon={ showCloseIcon }
            autoFocus={ autoFocus }
            stickyFormFooter={ stickyFormFooter }
            enableBackgroundUI={ enableBackgroundUI }
            disableEscKey={ disableEscKey }
            ariaRole={ ariaRole }
            onClick={ handleClick }
          />
        </State>

    );
  }, {
    notes: { markdown: notes },
    knobs: { escapeHTML: false }
  });
<commit_msg>replace to dialog style components<commit_after>import React from 'react';
import { storiesOf } from '@storybook/react';
import { text, select, boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import { State, Store } from '@sambego/storybook-state';
import OptionsHelper from '../../utils/helpers/options-helper';
import notes from './documentation/notes.md';
import Button from '../button/button';
import Dialog from './dialog.component';

const store = new Store({
  open: false
});

const handleCancel = (evt) => {
  store.set({ open: false });
  action('cancel')(evt);
};

const handleOpen = (evt) => {
  store.set({ open: true });
  action('open')(evt);
};

const handleClick = (evt) => {
  action('click')(evt);
};

storiesOf('Dialog', module)
  .addParameters({
    info: {
      propTablesExclude: [Button, State]
    }
  })
  .add('default', () => {
    const height = text('height', '400');
    const title = text('title', 'Example Dialog');
    const subtitle = text('subtitle', 'Example Subtitle');
    const size = select('size', OptionsHelper.sizesRestricted, Dialog.defaultProps.size);
    const showCloseIcon = boolean('showCloseIcon', Dialog.defaultProps.showCloseIcon);
    const autoFocus = boolean('autoFocus', Dialog.defaultProps.autoFocus);
    const stickyFormFooter = boolean('stickyFormFooter', false);
    const enableBackgroundUI = boolean('enableBackgroundUI', false);
    const disableEscKey = boolean('disableEscKey', false);
    const ariaRole = text('ariaRole', Dialog.defaultProps.ariaRole);

    return (

        <Button onClick={ handleOpen }>Open Preview</Button>
        <State store={ store }>
          <Dialog
            open={ store.get('open') }
            onCancel={ handleCancel }
            height={ height }
            title={ title }
            subtitle={ subtitle }
            size={ size }
            showCloseIcon={ showCloseIcon }
            autoFocus={ autoFocus }
            stickyFormFooter={ stickyFormFooter }
            enableBackgroundUI={ enableBackgroundUI }
            disableEscKey={ disableEscKey }
            ariaRole={ ariaRole }
            onClick={ handleClick }
          />
        </State>

    );
  }, {
    notes: { markdown: notes },
    knobs: { escapeHTML: false }
  });
<|endoftext|>


<commit_before>dojo.provide("dijit.form.Textarea");

dojo.require("dijit.form._FormWidget");
dojo.require("dojo.i18n");
dojo.requireLocalization("dijit.form", "Textarea");

dojo.declare(
	"dijit.form.Textarea",
	dijit.form._FormWidget,
{
	// summary
	//	A textarea that resizes vertically to contain the data.
	//	Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.
	//	Cols is not supported and the width should be specified with style width.
	//	Rows is not supported since this widget adjusts the height.
	// usage:
	//	<textarea dojoType="dijit.form.TextArea">...</textarea>

	templateString: (dojo.isIE || dojo.isSafari || dojo.isMozilla) ? '<fieldset id="${id}" class="dijitInlineBox dijitInputField dijitTextArea">'
				+ ((dojo.isIE || dojo.isSafari) ? '

'
					: '')
				+ '<textarea name="${name}" value="${value}" dojoAttachPoint="formValueNode" style="display:none;"></textarea>'
				+ '</fieldset>'
			: '<textarea id="${id}" name="${name}" value="${value}" dojoAttachPoint="formValueNode,editNode" class="dijitInputField dijitTextArea"></textarea>',

	_nlsResources: null,	// Needed for screen readers on FF2

	focus: function(){
		// summary: Received focus, needed for the InlineEditBox widget
		if(!this.disabled){
			this._changing(); // set initial height
		}
		if(dojo.isMozilla){
			dijit.focus(this.iframe);
		}else{
			dijit.focus(this.focusNode);
		}
	},

	_setFormValue: function(/*Boolean, optional*/ priorityChange){
		// blah
blah --> blah\nblah
		//
blah

blah
 --> blah\nblah
		//
blah

blah
 --> blah\nblah
		// &< > --> &< >
		value = this.editNode.innerHTML.replace(/<(br[^>]*|\/(p|div))>$|^<(p|div)[^>]*>|\r/gi,"").replace(/<\/(p|div)>\s*<\1[^>]*>|<(br|p|div)[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&/gi,"\&").replace(/ /gi," ").replace(/</gi,"<").replace(/>/gi,">");
		this.formValueNode.value = value;
		if(this.iframe){
			var d = this.iframe.contentWindow.document;
			var newHeight = d.body.firstChild.scrollHeight;
			if(d.body.scrollWidth > d.body.clientWidth){ newHeight+=16; } // scrollbar space needed?
			if(this.lastHeight != newHeight){ // cache size so that we don't get a resize event because of a resize event
				if(newHeight == 0){ newHeight = 16; } // height = 0 causes the browser to not set scrollHeight
				dojo.contentBox(this.iframe, {h: newHeight});
				this.lastHeight = newHeight;
			}
		}
		dijit.form.Textarea.superclass.setValue.call(this, value, priorityChange);
	},

	setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){
		var node = this.editNode;
		if(node){
			node.innerHTML = ""; // wipe out old nodes
			dojo.forEach(value.split("\n"), function(line){
				node.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited
				node.appendChild(document.createElement("BR")); // preserve line breaks
			});
		}
		this._setFormValue(priorityChange);
	},

	getValue: function(){
		return this.formValueNode.value;
	},

	postMixInProperties: function(){
		dijit.form.Textarea.superclass.postMixInProperties.apply(this,arguments);
		// don't let the source text be converted to a DOM structure since we just want raw text
		if(this.srcNodeRef && this.srcNodeRef.innerHTML != ""){
			this.value = this.srcNodeRef.innerHTML;
			this.srcNodeRef.innerHTML = "";
		}
		if((!this.value || this.value == "") && this.srcNodeRef && this.srcNodeRef.value){
			this.value = this.srcNodeRef.value;
		}
		if(!this.value){ this.value = ""; }
	},

	postCreate: function(){
		if(dojo.isIE || dojo.isSafari){
			this.domNode.style.overflowY = 'hidden';
			this.eventNode = this.focusNode = this.editNode;
			this.connect(this.eventNode, "oncut", this._changing);
			this.connect(this.eventNode, "onpaste", this._changing);
		}else if(dojo.isMozilla){
			var w = this.iframe.contentWindow;
			var d = w.document;
			// In the case of Firefox an iframe is used and when the text gets focus,
			// focus is fired from the document object.  There isn't a way to put a
			// waiRole on the document object and as a result screen readers don't
			// announce the role.  As a result screen reader users are lost.
			//
			// An additional problem is that the browser gives the document object a
			// very cryptic accessible name, e.g.
			// wyciwyg://13/http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/test_InlineEditBox.html
			// When focus is fired from the document object, the screen reader speaks
			// the accessible name.  The cyptic accessile name is confusing.
			//
			// A workaround for both of these problems is to give the iframe's
			// document a title, the name of which is similar to a role name, i.e.
			// "edit area".  This will be used as the accessible name which will replace
			// the cryptic name and will also convey the role information to the user.
			// Because it is read directly to the user, the string must be localized.
			this._nlsResources = dojo.i18n.getLocalization("dijit.form", "Textarea");
			d.open();
			d.write('<title>' +
				this._nlsResources.iframeTitle1 +	// "edit area"
				'</title>

');
			d.close();
			try{ this.iframe.contentDocument.designMode="on"; }catch(e){/*squelch*/} // this can fail if display:none
			this.editNode = d.body.firstChild;
			this.domNode.style.overflowY = 'hidden';
			this.eventNode = d;
			this.focusNode = this.editNode;
			this.eventNode.addEventListener("resize", dojo.hitch(this, "_changed"), false);
		}else{
			this.focusNode = this.domNode;
		}
		if(this.eventNode){
			this.connect(this.eventNode, "keypress", this._onKeyPress);
			this.connect(this.eventNode, "mousemove", this._changed);
			this.connect(this.eventNode, "focus", this._focused);
			this.connect(this.eventNode, "blur", this._blurred);
		}
		if(this.editNode){
			this.connect(this.editNode, "change", this._changed); // needed for mouse paste events per #3479
		}
		this.inherited('postCreate', arguments);
	},

	// event handlers, you can over-ride these in your own subclasses
	_focused: function(e){
		dojo.addClass(this.domNode, "dijitInputFieldFocused");
		this._changed(e);
	},

	_blurred: function(e){
		dojo.removeClass(this.domNode, "dijitInputFieldFocused");
		this._changed(e, true);
	},

	_onIframeBlur: function(){
		// Reset the title back to "edit area".
		this.iframe.contentDocument.title = this._nlsResources.iframeTitle1;
	},

	_onKeyPress: function(e){
		if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){
			// Pressing the tab key in the iframe (with designMode on) will cause the
			// entry of a tab character so we have to trap that here.  Since we don't
			// know the next focusable object we put focus on the iframe and then the
			// user has to press tab again (which then does the expected thing).
			// A problem with that is that the screen reader user hears "edit area"
			// announced twice which causes confusion.  By setting the
			// contentDocument's title to "edit area frame" the confusion should be
			// eliminated.
			this.iframe.contentDocument.title = this._nlsResources.iframeTitle2;
			// Place focus on the iframe. A subsequent tab or shift tab will put focus
			// on the correct control.
			// Note: Can't use this.focus() because that results in a call to
			// dijit.focus and if that receives an iframe target it will set focus
			// on the iframe's contentWindow.
			this.iframe.focus();  // this.focus(); won't work
			e.preventDefault();
			e.stopPropagation();
		}else{
			this.inherited("_onKeyPress", arguments);
		}
		if(this.iframe){
			// #3752:
			// The key press will not make it past the iframe.
			// If a widget is listening outside of the iframe, (like InlineEditBox)
			// it will not hear anything.
			// Create an equivalent event so everyone else knows what is going on.
			var te = document.createEvent("KeyEvents");
			te.initKeyEvent("keypress", true, true, null, false, false, false, false, e.charCode, e.charCode);
			this.iframe.dispatchEvent(te);
		}
		this._changing();
	},

	_changing: function(e){
		// summary: event handler for when a change is imminent
		setTimeout(dojo.hitch(this, "_changed", e, false), 1);
	},

	_changed: function(e, priorityChange){
		// summary: event handler for when a change has already happened
		if(this.iframe && this.iframe.contentDocument.designMode != "on"){
			this.iframe.contentDocument.designMode="on"; // in case this failed on init due to being hidden
		}
		this._setFormValue(priorityChange);
	},

	resize:function(/*Object*/ contentBox){
		// summary: set content box size
		dojo.contentBox(this.iframe || this.focusNode, {w:contentBox.w});
	}
});
<commit_msg>TextArea prevents Enter from bubbling, enabling InlineEditBox autoSave to work.  Fixes #3752. Patch from Mark Hays (IBM, CCLA on file)<commit_after>dojo.provide("dijit.form.Textarea");

dojo.require("dijit.form._FormWidget");
dojo.require("dojo.i18n");
dojo.requireLocalization("dijit.form", "Textarea");

dojo.declare(
	"dijit.form.Textarea",
	dijit.form._FormWidget,
{
	// summary
	//	A textarea that resizes vertically to contain the data.
	//	Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.
	//	Cols is not supported and the width should be specified with style width.
	//	Rows is not supported since this widget adjusts the height.
	// usage:
	//	<textarea dojoType="dijit.form.TextArea">...</textarea>

	templateString: (dojo.isIE || dojo.isSafari || dojo.isMozilla) ? '<fieldset id="${id}" class="dijitInlineBox dijitInputField dijitTextArea">'
				+ ((dojo.isIE || dojo.isSafari) ? '

'
					: '')
				+ '<textarea name="${name}" value="${value}" dojoAttachPoint="formValueNode" style="display:none;"></textarea>'
				+ '</fieldset>'
			: '<textarea id="${id}" name="${name}" value="${value}" dojoAttachPoint="formValueNode,editNode" class="dijitInputField dijitTextArea"></textarea>',

	_nlsResources: null,	// Needed for screen readers on FF2

	focus: function(){
		// summary: Received focus, needed for the InlineEditBox widget
		if(!this.disabled){
			this._changing(); // set initial height
		}
		if(dojo.isMozilla){
			dijit.focus(this.iframe);
		}else{
			dijit.focus(this.focusNode);
		}
	},

	_setFormValue: function(/*Boolean, optional*/ priorityChange){
		// blah
blah --> blah\nblah
		//
blah

blah
 --> blah\nblah
		//
blah

blah
 --> blah\nblah
		// &< > --> &< >
		value = this.editNode.innerHTML.replace(/<(br[^>]*|\/(p|div))>$|^<(p|div)[^>]*>|\r/gi,"").replace(/<\/(p|div)>\s*<\1[^>]*>|<(br|p|div)[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&/gi,"\&").replace(/ /gi," ").replace(/</gi,"<").replace(/>/gi,">");
		this.formValueNode.value = value;
		if(this.iframe){
			var d = this.iframe.contentWindow.document;
			var newHeight = d.body.firstChild.scrollHeight;
			if(d.body.scrollWidth > d.body.clientWidth){ newHeight+=16; } // scrollbar space needed?
			if(this.lastHeight != newHeight){ // cache size so that we don't get a resize event because of a resize event
				if(newHeight == 0){ newHeight = 16; } // height = 0 causes the browser to not set scrollHeight
				dojo.contentBox(this.iframe, {h: newHeight});
				this.lastHeight = newHeight;
			}
		}
		dijit.form.Textarea.superclass.setValue.call(this, value, priorityChange);
	},

	setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){
		var node = this.editNode;
		if(node){
			node.innerHTML = ""; // wipe out old nodes
			dojo.forEach(value.split("\n"), function(line){
				node.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited
				node.appendChild(document.createElement("BR")); // preserve line breaks
			});
		}
		this._setFormValue(priorityChange);
	},

	getValue: function(){
		return this.formValueNode.value;
	},

	postMixInProperties: function(){
		dijit.form.Textarea.superclass.postMixInProperties.apply(this,arguments);
		// don't let the source text be converted to a DOM structure since we just want raw text
		if(this.srcNodeRef && this.srcNodeRef.innerHTML != ""){
			this.value = this.srcNodeRef.innerHTML;
			this.srcNodeRef.innerHTML = "";
		}
		if((!this.value || this.value == "") && this.srcNodeRef && this.srcNodeRef.value){
			this.value = this.srcNodeRef.value;
		}
		if(!this.value){ this.value = ""; }
	},

	postCreate: function(){
		if(dojo.isIE || dojo.isSafari){
			this.domNode.style.overflowY = 'hidden';
			this.eventNode = this.focusNode = this.editNode;
			this.connect(this.eventNode, "oncut", this._changing);
			this.connect(this.eventNode, "onpaste", this._changing);
		}else if(dojo.isMozilla){
			var w = this.iframe.contentWindow;
			var d = w.document;
			// In the case of Firefox an iframe is used and when the text gets focus,
			// focus is fired from the document object.  There isn't a way to put a
			// waiRole on the document object and as a result screen readers don't
			// announce the role.  As a result screen reader users are lost.
			//
			// An additional problem is that the browser gives the document object a
			// very cryptic accessible name, e.g.
			// wyciwyg://13/http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/test_InlineEditBox.html
			// When focus is fired from the document object, the screen reader speaks
			// the accessible name.  The cyptic accessile name is confusing.
			//
			// A workaround for both of these problems is to give the iframe's
			// document a title, the name of which is similar to a role name, i.e.
			// "edit area".  This will be used as the accessible name which will replace
			// the cryptic name and will also convey the role information to the user.
			// Because it is read directly to the user, the string must be localized.
			this._nlsResources = dojo.i18n.getLocalization("dijit.form", "Textarea");
			d.open();
			d.write('<title>' +
				this._nlsResources.iframeTitle1 +	// "edit area"
				'</title>

');
			d.close();
			try{ this.iframe.contentDocument.designMode="on"; }catch(e){/*squelch*/} // this can fail if display:none
			this.editNode = d.body.firstChild;
			this.domNode.style.overflowY = 'hidden';
			this.eventNode = d;
			this.focusNode = this.editNode;
			this.eventNode.addEventListener("resize", dojo.hitch(this, "_changed"), false);
		}else{
			this.focusNode = this.domNode;
		}
		if(this.eventNode){
			this.connect(this.eventNode, "keypress", this._onKeyPress);
			this.connect(this.eventNode, "mousemove", this._changed);
			this.connect(this.eventNode, "focus", this._focused);
			this.connect(this.eventNode, "blur", this._blurred);
		}
		if(this.editNode){
			this.connect(this.editNode, "change", this._changed); // needed for mouse paste events per #3479
		}
		this.inherited('postCreate', arguments);
	},

	// event handlers, you can over-ride these in your own subclasses
	_focused: function(e){
		dojo.addClass(this.domNode, "dijitInputFieldFocused");
		this._changed(e);
	},

	_blurred: function(e){
		dojo.removeClass(this.domNode, "dijitInputFieldFocused");
		this._changed(e, true);
	},

	_onIframeBlur: function(){
		// Reset the title back to "edit area".
		this.iframe.contentDocument.title = this._nlsResources.iframeTitle1;
	},

	_onKeyPress: function(e){
		if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){
			// Pressing the tab key in the iframe (with designMode on) will cause the
			// entry of a tab character so we have to trap that here.  Since we don't
			// know the next focusable object we put focus on the iframe and then the
			// user has to press tab again (which then does the expected thing).
			// A problem with that is that the screen reader user hears "edit area"
			// announced twice which causes confusion.  By setting the
			// contentDocument's title to "edit area frame" the confusion should be
			// eliminated.
			this.iframe.contentDocument.title = this._nlsResources.iframeTitle2;
			// Place focus on the iframe. A subsequent tab or shift tab will put focus
			// on the correct control.
			// Note: Can't use this.focus() because that results in a call to
			// dijit.focus and if that receives an iframe target it will set focus
			// on the iframe's contentWindow.
			this.iframe.focus();  // this.focus(); won't work
			e.preventDefault();
			e.stopPropagation();
		}else if(e.keyCode == dojo.keys.ENTER){
			e.stopPropagation();
		}else{
			this.inherited("_onKeyPress", arguments);
		}
		if(this.iframe && e.keyCode != dojo.keys.ENTER){
			// #3752:
			// The key press will not make it past the iframe.
			// If a widget is listening outside of the iframe, (like InlineEditBox)
			// it will not hear anything.
			// Create an equivalent event so everyone else knows what is going on.
			var te = document.createEvent("KeyEvents");
			te.initKeyEvent("keypress", true, true, null, false, false, false, false, e.charCode, e.charCode);
			this.iframe.dispatchEvent(te);
		}
		this._changing();
	},

	_changing: function(e){
		// summary: event handler for when a change is imminent
		setTimeout(dojo.hitch(this, "_changed", e, false), 1);
	},

	_changed: function(e, priorityChange){
		// summary: event handler for when a change has already happened
		if(this.iframe && this.iframe.contentDocument.designMode != "on"){
			this.iframe.contentDocument.designMode="on"; // in case this failed on init due to being hidden
		}
		this._setFormValue(priorityChange);
	},

	resize:function(/*Object*/ contentBox){
		// summary: set content box size
		dojo.contentBox(this.iframe || this.focusNode, {w:contentBox.w});
	}
});
<|endoftext|>