text:
Array.prototype.getUnique = function(){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
};

function QuantizeIndicatorScale() {

    QuantizeIndicatorScale.prototype.setup = function (manager, options) {

        var nb_breaks = manager.colors.length;
        if (manager.indicator_data_raw.length < nb_breaks) {
            nb_breaks = manager.indicator_data_raw.length;
        }

        this.scale = d3.scale.quantize()
            .domain([d3.min(manager.indicator_data_raw), d3.max(manager.indicator_data_raw)])
            .range(d3.range(nb_breaks).map(function(i) { return manager.colors[i]; }));
    };

    QuantizeIndicatorScale.prototype.boundaries_for_color = function (color) {
        return this.scale.invertExtent(color);
    };

    QuantizeIndicatorScale.prototype.color_for_value = function (data) {
        return this.scale(data);
    };

    QuantizeIndicatorScale.prototype.available_colors = function () {
        return this.scale.range();
    };

}

function FixedBoundariesScale(options) {

    this.options = options;

    FixedBoundariesScale.prototype.setup = function (manager) {
        this.colors = [];
        this.min = d3.min(manager.indicator_data_raw);
        this.max = d3.max(manager.indicator_data_raw);

        if (this.options.steps) {
            this.steps = this.options.steps;
            for (var i=0; i < this.steps.length; i++) {
                this.colors.push(manager.colors[i]);
            }
        } else {
            var nb_breaks = manager.colors.length;
            if (manager.indicator_data_raw.length < nb_breaks) {
                nb_breaks = manager.indicator_data_raw.length;
            }

            var step = this.max / nb_breaks;
            var steps = [];
            var current = this.min;
            steps.push(this.min);
            for (var j=0; j< nb_breaks; j++) {
                steps.push(current + step);
                this.colors.push(manager.colors[j]);
            }
            this.steps = steps;
        }
    };

    FixedBoundariesScale.prototype.boundaries_for_color = function (color) {
        var index = this.colors.indexOf(color);
        if (index + 1 >= this.steps.length && this.max > this.steps[index]) {
            upper_bound = this.max;
        } else {
            upper_bound = this.steps[index + 1];
        }

        if (index === 0 && this.min < this.steps[index]) {
            lower_bound = this.min;
        } else {
            lower_bound = this.steps[index];
        }
        return [lower_bound, upper_bound];
    };

    FixedBoundariesScale.prototype.color_for_value = function (data) {
        for (var i=this.steps.length - 1; i>=0; i--) {
            if (data >= this.steps[i]) {
                return this.colors[i];
            }
        }
        return this.colors[this.colors.length -1];
    };

    FixedBoundariesScale.prototype.available_colors = function () {
        return this.colors;
    };
}

function getMalariaMapManager(options) {

    function MalariaMapManager(options) {

        this.symbols = "abcdefghijklmnopqrstuvwxyz0123456789";
        this.color_is_missing = '#1d3f61'; // '#353f41';
        this.color_not_expected = '#737780'; //'#bfe1e6';
        this.color_regular_point = '#6f9bd1';
        this.color_yes = '#889f37'; //'#28ff00';
        this.color_no = '#4d2c74'; //'#ff1500';
        this.colors = options.colors || ["#fef0d9", "#fdcc8a", "#fc8d59", "#d7301f"];
        this.tiles_url_tmpl = options.tiles_url_tmpl || 'https://{s}.tiles.sante.gov.ml/default/#SLUG#-#SUFFIX#/{z}/{x}/{y}.png';
        this.default_tiles_url_tmpl = 'https://{s}.tiles.sante.gov.ml/default/#SLUG#-#SUFFIX#/{z}/{x}/{y}.png';
        this.base_layer_url = 'https://{s}.tiles.sante.gov.ml/mali-base/{z}/{x}/{y}.png';
        this.marker_url_tmpl = 'https://tiles.sante.gov.ml/markers/#FILE#';
        this.dont_use_default_tiles = options.dont_use_default_tiles || false;
        this.initial_latitude = 14.0512;
        this.initial_longitude = -5.519499;
        this.initial_zoom = 8;
        this.mapID = options.mapID || "map";
        this.indicator_api_url = options.indicator_api_url || "/api/malaria/indicators";
        this.geojson_api_url = options.geojson_api_url || "/api/malaria/geojson/";
        this.default_region = options.default_region || "2732";

        // Internet Explorer needs tiles on same domain.
        if (navigator.userAgent.match(/Trident/)) {
        	this.tiles_url_tmpl = this.tiles_url_tmpl
        		.replace('{s}.tiles.sante.gov.ml/', 'snisi.sante.gov.ml/tiles/');
        	this.base_layer_url = this.base_layer_url
        		.replace('{s}.tiles.sante.gov.ml/', 'snisi.sante.gov.ml/tiles/');
        }

        this.map = null; // Mapbox map object
        this.scale = null; // Mapbox scale control
        this.legend = null; // Mapbox on-map legend
        this.hc_legend = null; // Mapbox on-map legend for static matrix
        this.infobox = null; // Mapbox infobox control

        this.districts_layer = options.districts_layer || null; // Mapbox layer for districts
        this.hc_layer = options.hc_layer || null; // Mapbox layer for Health Centers

        this.indicator_scale = options.indicator_scale || new QuantizeIndicatorScale();

        this.title = options.title || null;
        this.subtitle = options.subtitle || null;

        // DOM elements of UI parts.
        this.map_title_e = null; // html title on top of map
        this.map_subtitle_e = null; // html sub title (date/entity)

        this.tabbar_e = null;
        this.district_select = null;
        this.indicator_section_select = null;
        this.indicator_select = null;
        this.year_select = null;
        this.month_select = null;

        this.getEmptyOption = function () {
            return $('<option value="-1">AUCUN</option>');
        };

        // Data that should be always accurate
        this.indicator_data = options.indicator_data || {};
        this.indicator_data_hc = options.indicator_data_hc || {};
        this.geodata = options.geodata || null;
        this.month = options.month || null; // 1-12 number of month selected
        this.month_name = options.month_name || null; // display-name of month
        this.year = options.year || null;

        this.indicators_list = options.indicators || {};
        this.current_region = options.current_region || null; // selected region slug
        this.current_district = options.current_district || null; // selected district slug
        this.current_indicator_section = null; // selected indicator section
        this.current_indicator = options.current_indicator || null; // selected indicator slug
        this.current_indicator_name = options.current_indicator_name || null; // selected indicator name

        this.static_map = options.static_map || false;

        this.load(options.load, options.onload);

    }

    MalariaMapManager.prototype.export_props = function() {
        return {
            title: this.title,
            subtitle: this.subtitle,
            current_region: this.current_region,
            current_district: this.current_district,
            current_indicator: this.current_indicator,
            current_indicator_name: this.current_indicator_name,
            year: this.year,
            month: this.month,
            month_name: this.month_name,
            geodata: this.geodata,
            indicators: this.indicators,
            indicator_data: this.indicator_data,
            indicator_data_hc: this.indicator_data_hc,
            indicator_scale: this.indicator_scale,
            // districts_layer: this.districts_layer,
            // hc_layer: this.hc_layer,

			colors: this.colors,
			tiles_url_tmpl: this.tiles_url_tmpl,
			dont_use_default_tiles: this.dont_use_default_tiles,
			indicator_api_url: this.indicator_api_url,
			geojson_api_url: this.geojson_api_url
        };
    };

    MalariaMapManager.prototype._prepare_map = function() {
        // remove user interactions
        var options = {
            dragging: false,
            touchZoom: false,
            scrollWheelZoom: false,
            doubleClickZoom: false,
            boxZoom: false,
            zoomControl: false,
            attributionControl: false
        };

        if (this.static_map) {
            options.fadeAnimation = false;
            options.zoomAnimation = false;
            options.markerZoomAnimation = false;
        }

        this.map = L.mapbox.map(this.mapID, null, options);

        // background layer
        this.base_layer = L.tileLayer(this.base_layer_url)
                                  .addTo(this.map);

        // add a scale
        this.scale = L.control.scale({imperial:false})
                              .addTo(this.map);

        this.map.setView([this.initial_latitude, this.initial_longitude],
                         this.initial_zoom);

        this._prepare_map_legend();
        if (!this.static_map) {
            this._prepare_map_infobox();
        }
    };

    MalariaMapManager.prototype._prepare_map_legend = function () {
        var manager = this;

        this.legend = L.control({position: 'bottomright'});
        this.legend.onAdd = function (map) {
            this.div = L.DomUtil.create('div', 'info legend');
            this.update();
            return this.div;
        };
        this.legend.update = function() {

            var labels = [];

            function cleanNum(num) {
                return Math.round(num * 10) / 10;
            }

            $.each(manager.colors, function(index) {
                var color = manager.colors[index];
                var label = null;
                // boundaries = manager.indicator_scale.invertExtent(color);
                boundaries = manager.indicator_scale.boundaries_for_color(color);
                if (boundaries.length == 2 && !isNaN(boundaries[0]) && !isNaN(boundaries[1])) {
                    var from = boundaries[0];
                    var to = boundaries[1];

                    if (index !== 0) { from += 0.1; }

                    labels.push(
                        ' ' +
                        cleanNum(from) + ' – ' +
                        cleanNum(to) + '');
                }
            });

            // SPACER
            if (labels.length) {
                labels.push(' ');
            }

            // NOT EXPECTED
            labels.push(
                ' n/a');

            // MISSING
            labels.push(
                ' manquant');

            this.div.innerHTML = labels.join('
');
        };
    };

    MalariaMapManager.prototype._prepare_map_hc_legend = function () {
        var manager = this;

        if (!this.static_map) {
            return;
        }

        this.hc_legend = L.control({position: 'topleft'});
        this.hc_legend.onAdd = function (map) {
            this.div = L.DomUtil.create('div', 'info hc_legend');
            this.update();
            return this.div;
        };
        this.hc_legend.update = function() {

            var labels = [];

            hc_lines = [];
            var l = manager.getCurrentDistrict().properties.children.features.length;
            for (var index=0; index<l; index++) {
                var feature = manager.getCurrentDistrict().properties.children.features[index];
                var slug = feature.properties.slug;
                if (feature !== null) {
                    var data = manager.getHCDataForSlug(slug).hdata;
                    // if (data == 1.replace('.00%', '%');
                    // var label = ''+ feature.properties.name + ': ' + data +'';
                    var label = ''+ feature.properties['hc_legend_name'] +'';
                    hc_lines.push(label);
                }
            }
            labels.push('
' + hc_lines.join('
') + '
');

            this.div.innerHTML = labels.join('
');
        };
    };

    MalariaMapManager.prototype._prepare_map_infobox = function () {
        var manager = this;
        this.infobox = L.control();
        this.infobox.onAdd = function (map) {
            this._div = L.DomUtil.create('div', 'info');
            this.update();
            return this._div;
        };
        this.infobox.update = function (feature) {
            if (feature === undefined) {
                this._div.innerHTML = 'Déplacez la souris sur les districts.';
                return;
            }
            var text, d = manager.getDataForSlug(feature.properties.slug);
            if (d === null || d === undefined)
                text = feature.properties.display_typed_name;
            else
                text = feature.properties.name + ' : ' + d.hdata;
            this._div.innerHTML = '' + text + '';
        };
        this._addInfoBox();
    };

    MalariaMapManager.prototype._prepareUI = function() {
        var manager = this;

        this.map_title_e = $('#map_title');
        this.map_subtitle_e = $('#map_subtitle');

        this.tabbar_e = $('#tab_bar');

        this.district_select = $('#health_district_select');
        this.district_select.on('change', function (event) {
            console.log("district select changed");
            var ds = manager.district_select.val();
            manager.current_district = (ds == '-1') ? null : ds;

            manager.parametersChanged();
        });

        this.indicator_select = $('#indicator_select');
        this.indicator_select.on('change', function (event) {
            console.log("indicator select changed");
            var is = manager.indicator_select.val();
            manager.current_indicator = (is == '-1') ? null : is;
            manager.current_indicator_name = (manager.current_indicator === null) ? "" :
            manager.indicator_select.children('option:selected').text();

            manager.parametersChanged();

            // switchIndicator
            // manager.loadIndicator();
        });

        this.indicator_section_select = $('#indicator_section_select');
        var default_domain = "Tous";
        $.each(this.indicators_list, function (section_name) {
        	var domain = default_domain;
        	console.log(section_name);
        	if (section_name.indexOf("#") != -1) {
        		var aOs = section_name.split("#");
        		var domain = aOs[0];
        		var section_name = aOs[1];
        	}

            var opt = $('<option />');
            opt.attr('value', section_name);
            opt.text(section_name);

    		var optgroups = manager.indicator_section_select.find("optgroup[label=" + domain +"]");
    		console.log(optgroups);
    		if (optgroups.length == 0) {
    			domain_elem = $('<optgroup />');
    			domain_elem.attr('label', domain);
    			manager.indicator_section_select.append(domain_elem);
    		} else {
    			console.log("FOUND");
    			domain_elem = optgroups[0];
    		}
    		console.log(domain_elem);
        	$(domain_elem).append(opt);
        });
        this.indicator_section_select.on('change', function (event) {
            console.log("indicator section select changed");
            var iss = manager.indicator_section_select.val();
            manager.current_indicator_section = (iss == '-1') ? null : iss;

            // update indiciator list
            manager.indicator_select.empty();
            manager.indicator_select.append(manager.getEmptyOption());
            var list = manager.indicators_list[manager.current_indicator_section];
            $.each(list, function (index) {
                var opt = $('<option />');
                opt.attr('value', list[index].slug);
                opt.text(list[index].name);
                manager.indicator_select.append(opt);
            });
            manager.indicator_select.change();

            manager.parametersChanged();
        });
        this.indicator_section_select.change();

        this.year_select = $('#year_select');
        this.year_select.on('change', function (event) {
            console.log("year select changed");
            manager.year = manager.year_select.val();
            manager.parametersChanged();

            // switchIndicator
            manager.loadIndicator();
        });
        this.year_select.change();

        this.month_select = $('#month_select');
        this.month_select.on('change', function (event) {
            console.log("month select changed");
            manager.month = manager.month_select.val();
            manager.month_name = manager.month_select.children('option:selected').text();
            manager.parametersChanged();

            // switchIndicator
            manager.loadIndicator();
        });
        this.month_select.change();
    };

    MalariaMapManager.prototype._prepareTabBar = function() {
        if (this.geodata === null) {
            console.log("NO GEODATA. NO BAR");
            return;
        }

        var manager = this;

        this.tabbar_e.empty();
        $.each(this.geodata, function (region_slug){
            var region = manager.getRegion(region_slug);
            var link = $('');
            link.attr('href', '#');
            link.attr('slug', region.properties.slug);
            link.text(region.properties.name);
            manager.tabbar_e.append(link);
        });

        this.tabbar_e.children('a').on('click',
            function (event) {
                event.preventDefault();
                manager.switchRegion($(this).attr('slug'));
            }
        );
    };

    MalariaMapManager.prototype.updateTabBar = function () {
        var manager = this;
        this.tabbar_e.children('a').each(function (index) {
            $(this).removeClass('active');
            if ($(this).attr('slug') == manager.current_region) {
                $(this).addClass('active');
            }
        });
    };

    MalariaMapManager.prototype.disableUI = function () {
    	var elems = [this.district_select,
        			 this.indicator_section_select,
        			 this.indicator_select,
        			 this.year_select,
        			 this.month_select];
        $.each(elems, function (index, elem) {
        	if (elem) {
        		elem.attr('disabled', 'disabled');
        	}
        });
    }

    MalariaMapManager.prototype.enableUI = function () {
    	var elems = [this.district_select,
        			 this.indicator_section_select,
        			 this.indicator_select,
        			 this.year_select,
        			 this.month_select];
        $.each(elems, function (index, elem) {
        	if (elem) {
        		elem.removeAttr('disabled');
        	}
        });
    }

    MalariaMapManager.prototype._updateDistrictSelect = function () {
        this.district_select.children("option[value="+ this.current_district +"]").attr('selected', 'selected');
    };

    MalariaMapManager.prototype.exitDistrict = function () {
        this.district_select.children("option[value='-1']").attr('selected', 'selected');
        this.district_select.change();
    };

    MalariaMapManager.prototype._updateIndicatorSelect = function () {
        var indicator_val = this.current_indicator || '-1';
        this.indicator_select.children("option[value="+ indicator_val +"]").attr('selected', 'selected');
        var indicator_section_val = this.current_indicator_section || '-1';
        this.indicator_section_select.children("option[value='"+ indicator_section_val +"']").attr('selected', 'selected');
    };

    MalariaMapManager.prototype.parametersChanged = function() {
        if (!this.isReady()) {
            return;
        }
        this._updateTitle();

        this._updateDistrictSelect();

        if (this.isIndicator()) {
        	var has_data = (Object.keys(this.indicator_data_hc).length) > 0;
	        if (has_data && this.isDistrict()) {
	        	this.exitDistrict();
	        	return;
	        }
            this.loadIndicator();
        } else {
            this.switchRegion(this.current_region);
        }

    };

    MalariaMapManager.prototype.getCurrentRegion = function () {
        return this.getRegion(this.current_region);
    };

    MalariaMapManager.prototype.getRegion = function (region_slug) {
        return this.geodata[region_slug];
    };

    MalariaMapManager.prototype.getDistrict = function (district_slug) {
        var ret = null;
        var region = this.getCurrentRegion();
        $.each(region.features, function (index) {
            var feature = region.features[index];
            if (feature.properties.slug == district_slug) {
                ret = feature;
                return;
            }
        });
        return ret;
    };

    MalariaMapManager.prototype.getHCFeature = function (hc_slug) {
        var ret = null;
        var district = this.getCurrentDistrict();
        $.each(district.properties.children.features, function (index) {
            var feature = district.properties.children.features[index];
            if (feature.properties.slug == hc_slug) {
                ret = feature;
                return;
            }
        });
        return ret;
    };

    MalariaMapManager.prototype.getCurrentDistrict = function () {
        return this.getDistrict(this.current_district);
    };

    MalariaMapManager.prototype.isDistrict = function () {
        return this.current_district !== null;
    };

    MalariaMapManager.prototype.isIndicator = function () {
        return this.current_indicator !== null;
    };

    MalariaMapManager.prototype.isReady = function () {
        return this.geodata !== null;
    };

    MalariaMapManager.prototype.getCurrentFeature = function () {
        if (this.isDistrict()) {
            return this.getCurrentDistrict();
        }
        return this.getCurrentRegion();
    };

    MalariaMapManager.prototype._updateTitle = function () {

        var period_str, location_str, indicator_str, title, subtitle;

        if (this.isIndicator()) {
            title = this.current_indicator_name;
            period_str = this.month_name + " " + this.year;
            location_str = this.getCurrentFeature().properties.display_typed_name;
            subtitle = location_str + ", " + period_str;
        } else {
            title = this.getCurrentFeature().properties.display_typed_name;
            subtitle = null;
        }

        this.title = title;
        this.subtitle = subtitle;

        this.map_title_e.text(this.title || "");
        this.map_subtitle_e.text(this.subtitle || "");

    };

    MalariaMapManager.prototype.resetUI = function () {

        // update titles
        this._updateTitle();

        // update district list & selected
        var region = this.getCurrentRegion();
        this.district_select.empty();
        this.district_select.append(this.getEmptyOption());
        for (var i=0 ; i< region.features.length ; i++) {
            var opt = $('<option />');
            opt.attr('value', region.features[i].properties.slug);
            opt.text(region.features[i].properties.name);
            this.district_select.append(opt);
        }

        // update legend: remove ?
        if (!this.isIndicator()){
            this._removeLegend();
        } else {
            this._addLegend();
            this.legend.update();
        }

        // update infobox: remove ?

    };

    MalariaMapManager.prototype._addInfoBox = function () {
        try {
            this.map.addControl(this.infobox);
        } catch (e) {}
    };

    MalariaMapManager.prototype._removeInfoBox = function () {
        try {
            this.map.removeControl(this.infobox);
        } catch (e) {}
    };

    MalariaMapManager.prototype._addLegend = function () {
        try {
            this.map.addControl(this.legend);
        } catch (e) {}
    };

    MalariaMapManager.prototype._removeLegend = function () {
        try {
            this.map.removeControl(this.legend);
        } catch (e) {}
    };

    MalariaMapManager.prototype.startLoadingUI = function() {
    	console.log("startLoadingUI");
    	this.disableUI();
        this.map.spin(true);
    };

    MalariaMapManager.prototype.stopLoadingUI = function() {
    	console.log("stopLoadingUI");
        this.map.spin(false);
        this.enableUI();
    };

	MalariaMapManager.prototype.maxLengthHcName = function() {
        var max = 0;
        var manager = this;
        $.each(manager.getCurrentDistrict().properties.children.features, function (index) {
            var feature = manager.getCurrentDistrict().properties.children.features[index];
            var l = feature.properties.name.length;
            if (l > max) {
                max = l;
            }
        });
        return max;
    };

    MalariaMapManager.prototype.removeHCLayer = function() {
        if (this.map.hasLayer(this.hc_layer)) {
            this.map.removeLayer(this.hc_layer);
        }
        this.indicator_data_hc = {};
    };

    MalariaMapManager.prototype.resetAfterExport = function(data) {
        this.displayDistrictLayer(this.indicator_data);
        if (this.isDistrict()) {
            this.displayHCLayer(this.indicator_data_hc);
        }
    };

    MalariaMapManager.prototype.displayHCLayer = function(data) {
        console.log("displayHCLayer 2");
        this.removeHCLayer();

    	// remove region-level district names
    	this.removeLayer(this.region_names_layer);
    	this.removeLayer(this.region_borders_layer);
    	this.removeLayer(this.district_border);

        // display district names based on this district
        this.region_names_layer = this.getTileLayer(this.current_district, 'NAMES', true);
        this.region_borders_layer = this.getTileLayer(this.current_region, 'BORDERS', true);
        this.district_border = this.getTileLayer(this.current_district, 'BORDER', true);

        var manager = this;

        this.indicator_data_hc = data;

        function props_from_feature(feature) {
            var label = feature.properties.name;
            var color = manager.color_regular_point;
            var d = manager.getHCDataForSlug(feature.properties.slug);
            var yesno_istrue = false;
            if (d === undefined) {
            } else if (d.is_missing) {
                label += ': manquant';
                color = manager.color_is_missing;
            } else if (d.is_not_expected) {
                label += ': non attendu';
                color = manager.color_not_expected;
            } else {
                if (d.is_yesno) {
                    // change color of data point for YES/NO
                    yesno_istrue = d.data > 0;
                    color = yesno_istrue ? manager.color_yes : manager.color_no;
                    label += ': ';
                    label += yesno_istrue ? 'OUI' : 'NON';
                } else {
                    label += ': ' + d.hdata;
                }
            }
            return {label: label, color: color, data: d, yesno_istrue: yesno_istrue};
        }

        var maxNameLength = d3.max(manager.getCurrentDistrict().properties.children.features.map(function(feature){ return feature.properties.name.length;}));
        var maxDataLength = d3.max(manager.getCurrentDistrict().properties.children.features.map(function(feature){ return props_from_feature(feature).data.hdata.length;}));
        var maxTotalLength = maxNameLength + maxDataLength;
        $.each(manager.getCurrentDistrict().properties.children.features, function (index) {
            var feature = manager.getCurrentDistrict().properties.children.features[index];
            var props = props_from_feature(feature);
            var symbol = (index >= manager.symbols.length) ? 'hospital' : manager.symbols[index];
            feature.properties['title'] = props.label;
            var iconUrl = manager.marker_url_tmpl.replace('#FILE#', 'pin-m-'+symbol+'-'+manager.getColorName(props.color)+'.png');

            feature.properties['icon'] = {
            	'iconUrl': iconUrl,
            	'iconSize': [30, 70],
            	"iconAnchor": [25, 25],
            	"popupAnchor": [0, -25]
            }

            // feature.properties['marker-size'] = 'medium';
            // feature.properties['marker-color'] = props.color;
            // feature.properties['marker-symbol'] = symbol;

            var hc_legend_name = (symbol.length > 1) ? '+' : symbol.toUpperCase() + ". " + feature.properties.name;
            var nl = feature.properties.name.length + props.data.hdata.length;
            if (nl < maxTotalLength) {
                for (var i = nl ; i < maxTotalLength ; i++) {
                    hc_legend_name += " ";
                }
            }
            hc_legend_name += "  " + props.data.hdata;
            feature.properties['hc_legend_name'] = hc_legend_name;
            manager.getCurrentDistrict().properties.children.features[index] = feature;
        });

        manager.hc_layer = L.mapbox.featureLayer();

		manager.hc_layer.on('layeradd', function(e) {
            var marker = e.layer;
            var feature = marker.feature;
			marker.setIcon(L.icon(feature.properties.icon));
        });

        if (!manager.static_map) {
            manager.hc_layer.on('mouseover', function(e) {
                e.layer.openPopup();
            });
            manager.hc_layer.on('mouseout', function(e) {
                e.layer.closePopup();
            });
        }
        manager.hc_layer.setGeoJSON(manager.getCurrentDistrict().properties.children);
        manager.hc_layer.addTo(manager.map);
    };

    MalariaMapManager.prototype.displayDistrictLayer = function(data) {
        this.removeHCLayer();
        var manager = this;
        manager.removeDistrictLayer();
        manager.indicator_data = data;
        manager.indicator_data_raw = [];

        // remove region static
        manager.removeLayer(this.region_layer);
        manager.removeLayer(this.region_borders_layer);

        // quit if no data (display region STATIC)
        if (!Object.keys(manager.indicator_data).length) {
            this.region_layer = this.getTileLayer(this.current_region, 'STATIC', true);
            // add border layer for region
            this.region_borders_layer = this.getTileLayer(this.current_region, 'BORDERS', true);
            return;
        } else {
        	// remove region layers
            this.removeLayer(this.region_layer);
        }
        // remove region borders
        manager.removeLayer(manager.region_borders_layer);
        // remove district names
        manager.removeLayer(manager.region_names_layer);

        // collect actual data for indicator
        $.each(manager.indicator_data, function (index) {
            var d = manager.indicator_data[index];
            if (!d.is_missing && !d.is_not_expected) {
                manager.indicator_data_raw.push(d.data);
            }
        });
        manager.indicator_data_raw = manager.indicator_data_raw.getUnique();
        manager.indicator_scale.setup(manager);

        // build all layers for districts
        manager.districts_layers = {};
        var getKey = function (feature, id) {
            return feature.properties.slug + '-' + id;
        };

        // var borderLayers = [];
        $.each(manager.getCurrentRegion().features, function (index) {
            var feature = manager.getCurrentRegion().features[index];
            var color = manager.getColorFor(manager.getDataForSlug(feature.properties.slug), true);
            var tileUrl = manager.getTileUrl(feature.properties.slug, manager.getColorName(color));
            // var tileBorderUrl = manager.getTileUrl(feature.properties.slug, 'BORDER');
            // var tileNamesUrl = manager.getTileUrl(feature.properties.slug, 'NAMES');

            manager.districts_layers[getKey(feature, 'shape')] = L.tileLayer(tileUrl, {opacity: manager.tileOpacity}).addTo(manager.map);
        });

        // add region district names if on a static map and not a district
        if (manager.static_map && !manager.isDistrict()) {
            //L.tileLayer(manager.getTileUrl(manager.getCurrentRegion(), 'NAMES')).addTo(manager.map);
        }

        manager.districts_layer = L.geoJson(manager.getCurrentRegion(), {
            style: function (feature) { return {fillOpacity: 0, opacity: 0}; },
            onEachFeature: function(feature, layer) {

                if (manager.static_map) {
                    if (manager.isDistrict() && feature.properties.slug == manager.current_district) {
                        // add
                        // manager.districts_layers[getKey(feature, 'names')].setOpacity(1);

                        // add border layer
                        // manager.districts_layers[getKey(feature, 'border')].setOpacity(1);
                    }
                    return;
                }

                layer.on('mouseover', function(event) {
                    var layer = event.target;
                    manager.infobox.update(layer.feature);

                    // switch border opacity ON
                    // manager.districts_layers[getKey(layer.feature, 'border')].setOpacity(1);
                    manager.districts_layers[feature.properties.slug+'-shape'].setOpacity(1);

                    if (!L.Browser.ie && !L.Browser.opera) {
                        if (manager.isDistrict()) {
                            try {
                                manager.hc_layer.bringToFront();
                            } catch (e) {}
                        }
                    }
                });

                layer.on('mouseout', function(event) {
                    // swicth border off
                    //manager.districts_layers[getKey(layer.feature, 'border')].setOpacity(0);

                    manager.districts_layers[feature.properties.slug+'-shape'].setOpacity(manager.tileOpacity);

                    if (!manager.isDistrict()) {
                        manager.infobox.update();
                    }
                });

                layer.on('click', function (e) {
                    manager.current_district = e.target.feature.properties.slug;
                    manager.parametersChanged();
                });

            }
        });

        manager.map.addLayer(manager.districts_layer);
        manager._addLegend();

        // we need to add region borders back
        this.region_borders_layer = this.getTileLayer(this.current_region, 'BORDERS', true);
        // as well as district names if not on a district
        if (!manager.isDistrict()) {
        	this.region_names_layer = this.getTileLayer(this.current_region, 'NAMES', true);
        }

    };

    MalariaMapManager.prototype.getTileLayer = function (feature_slug, suffix, add_to_map) {
    	var burl = this.getTileUrl(feature_slug, suffix);
    	var payload = {};
		$.ajax(burl.replace('{s}.', '').replace('{z}/{x}/{y}.png', 'metadata.json'), {async:false, }).success(function (data){
			try {
				var bs = data['bounds'].split(',');
				var southWest = L.latLng(parseFloat(bs[1]), parseFloat(bs[0])),
	    			northEast = L.latLng(parseFloat(bs[3]), parseFloat(bs[2])),
	    			bounds = L.latLngBounds(southWest, northEast);
	    	} catch (e) { console.log(e.toString()); console.log(data); var bounds = null; }
			payload = {
    			"bounds": bounds,
    			"minZoom": parseInt(data['minzoom']),
    			"maxZoom": parseInt(data['maxzoom']),
			};
    	});

		// this.getTileUrl(feature_slug, suffix);
    	var l = L.tileLayer(burl, payload);
    	if (add_to_map) {
    		l.addTo(this.map);
    	}
    	return l;
	};

    MalariaMapManager.prototype.getTileUrl = function (feature_slug, suffix) {
    	var turl = this.default_tiles_url_tmpl;
    	if (this.dont_use_default_tiles ||
    		[0, 1, 2, 3].indexOf(suffix) != -1) {
	    		turl = this.tiles_url_tmpl;
	    }
        return turl.replace('#SLUG#', feature_slug).replace('#SUFFIX#', suffix);
    };

    MalariaMapManager.prototype.removeLayer = function(layer) {
    	if (this.map.hasLayer(layer)) {
    		this.map.removeLayer(layer);
    	}

    };

    MalariaMapManager.prototype.removeDistrictLayer = function() {
        this.indicator_data = {};
        this._removeLegend();

        this.removeLayer(this.districts_layer);
    	this.removeLayer(this.district_border);
    	this.removeLayer(this.region_names_layer);
    	this.removeLayer(this.region_borders_layer);

    	if (this.districts_layers) {
    		var manager = this;
	        $.each(this.districts_layers, function (index, layer) {
	        	manager.removeLayer(layer);
	        });
	    }
    };

    MalariaMapManager.prototype.loadIndicator = function() {
        // probably just a parameter change (month/year)
        if (!this.isIndicator()) {
            return;
        }

        var region = this.current_region;

        var jsdata = JSON.stringify({
            entity_slug: this.getCurrentFeature().properties.slug,
            indicator_slug: this.current_indicator,
            year: this.year,
            month: this.month
        });

        this.startLoadingUI();
        var manager = this;
        $.post(this.indicator_api_url, jsdata, function (data) {
            try {
                if (manager.isDistrict()) {
                    manager.displayHCLayer(data);
                } else {
                    manager.removeHCLayer();
                    manager.displayDistrictLayer(data);
                }

                manager.updateZoom();
                manager.stopLoadingUI();
            } catch (exp) {
                console.log("catched expection");
                console.log(exp);
                manager.switchRegion(region);
            }

        }).fail(function () {
            console.log("failed JSON");
            manager.stopLoadingUI();
            manager.switchRegion(region);
        });
    };

    MalariaMapManager.prototype.removeLayer = function(layer) {
        if (this.map.hasLayer(layer)) {
            this.map.removeLayer(layer);
        }
    };

    MalariaMapManager.prototype.zoomTo = function (layer) {
        if (!layer)
        	return;
        try {
        	var bounds = layer.getBounds();
        } catch (e) {
        	try {
        		var bounds = layer.options.bounds;
        	} catch (ee) {
        		return;
        	}
        }
        this.map.fitBounds(bounds);
    };

    MalariaMapManager.prototype.getDistrictLayer = function (district_slug) {
        var layer = null;
        var manager = this;
        $.each(this.map._layers, function (index) {
            var l = manager.map._layers[index];
            try {
                if (l.feature.properties.slug == district_slug)
                    layer = l;
            } catch(e) {}
        });
        return layer;
    };

    MalariaMapManager.prototype.updateZoom = function () {
        var layer;
        var bounds = null;
        if (this.isDistrict()) {
            layer = this.getDistrictLayer(this.current_district);
        } else {
        	// we're at region static
        	if (this.map.hasLayer(this.region_layer)) {
        		layer = this.region_layer;
        	} else {
            	layer = this.districts_layer;
            }
        }
        if (this.current_region == "SSH3") {
			var southWest = L.latLng(12.833226023521243, -5.515136718749999),
				northEast = L.latLng(16.1724728083975, -0.9118652343749999);
			bounds = L.latLngBounds(southWest, northEast);
		}
		if (this.current_region == "4JN7") {
			var southWest = L.latLng(15.5847, -5.8767),
				northEast = L.latLng(11.4087, -9.2275);
			bounds = L.latLngBounds(southWest, northEast);
		}
		if (this.current_region == "GJM3") {
			var southWest = L.latLng(15.6826, -8.0245),
				northEast = L.latLng(11.8526, -12.2817);
			bounds = L.latLngBounds(southWest, northEast);
		}

        if (bounds) {
        	this.map.fitBounds(bounds);
        } else {
        	this.zoomTo(layer);
        }
    };

    MalariaMapManager.prototype.switchRegion = function(region_slug) {
        console.log("switching to region " + region_slug);
        this.startLoadingUI();
        this.current_region = region_slug;
        this.current_district = null;
        this.current_indicator = null;
        this.current_indicator_name = null;

        this._updateTitle();
        this.infobox.update();
        this._updateIndicatorSelect();
        this.removeHCLayer();

        // make sure UI is clean
        this.removeDistrictLayer();
        try {
            this.updateTabBar();
            this.resetUI();
        } catch(exp){}

        if (this.isIndicator()) {
            this.loadIndicator();
        } else {
            // this.districts_layer = L.geoJson(this.getCurrentRegion(), {
            //     style: this.noIndicatorStyle
            // });
            // this.map.addLayer(this.districts_layer);
            this.displayDistrictLayer({});
        }
        this.updateZoom();
        this.stopLoadingUI();
    };

    MalariaMapManager.prototype.prepare = function() {
        this._prepare_map();
        if (!this.static_map) {
            this._prepareUI();
        }
    };

    MalariaMapManager.prototype.loadStaticMap = function(callback) {

        // add legend
        this._addLegend();
        if (this.isDistrict()) {
            this._prepare_map_hc_legend();
            this.map.addControl(this.hc_legend);
        }

        var indicator_data_hc = this.indicator_data_hc;

        // display the layers we have
        if (this.indicator_data) {
            this.displayDistrictLayer(this.indicator_data);
        }

        // display HC layer
        if (this.isDistrict() && Object.keys(indicator_data_hc).length) {
            this.displayHCLayer(indicator_data_hc);
        }

        // zoom to current feature
        this.updateZoom();

        if (callback !== undefined) {
            callback(this);
        }
    };

    MalariaMapManager.prototype.loadGeoData = function(callback) {
        var manager = this;
        $.get(this.geojson_api_url, {},
            function (data) {
                console.log("received region GeoJSON");
                // saved geodata as it contains all our polygons & points
                manager.geodata = data;

                // display the region tab bar.
                manager._prepareTabBar();

                // display default region
                manager.switchRegion(manager.default_region);

                // launch callback
                if (callback !== undefined) {
                    callback(this);
                }
            }
        );
    };

    MalariaMapManager.prototype.load = function(loadData, callback) {
        this.prepare();
        if (loadData === true) {
            this.loadGeoData(callback);
        }
        if (this.static_map === true) {
            this.loadStaticMap(callback);
        }
    };

    MalariaMapManager.prototype.getDataForSlug = function(slug) {
        return this.indicator_data[slug];
    };

    MalariaMapManager.prototype.getHCDataForSlug = function(slug) {
        return this.indicator_data_hc[slug];
    };

    MalariaMapManager.prototype.getColorFor = function(data) {

        if (data === undefined)
            return this.color_is_missing;
        if (data.is_not_expected) {
            return this.color_not_expected;
        }
        if (data.is_missing) {
            return this.color_is_missing;
        }
        // var color = this.indicator_scale(data.data);
        var color = this.indicator_scale.color_for_value(data.data);
        // if (color === undefined && this.indicator_scale.range().length == 1) {
        if (color === undefined && this.indicator_scale.available_colors().length == 1) {
            color = this.colors[0];
        }
        return color;
    };

    MalariaMapManager.prototype.getColorName = function(color) {
    	index = this.colors.indexOf(color);
    	if (index == -1) {
    		if (color == this.color_is_missing) {
    			return 'MISSING';
    		}
    		if (color == this.color_not_expected) {
    			return 'NOT_EXPECTED';
    		}
    		if (color == this.color_regular_point) {
    			return 'REGULAR';
    		}
    		if (color == this.color_yes) {
    			return 'YES';
    		}
    		if (color == this.color_no) {
    			return 'NO';
    		}
    	} else {
    		return index;
    	}
    };

    MalariaMapManager.prototype.noIndicatorStyle = function (feature) {
        return {
            fillColor: "#6f9bd1",
            weight: 2,
            opacity: 1,
            color: 'white',
            fillOpacity: 1};
    };

    return new MalariaMapManager(options);
}

function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
  if (typeof stroke == "undefined" ) {
    stroke = true;
  }
  if (typeof radius === "undefined") {
    radius = 5;
  }
  ctx.beginPath();
  ctx.moveTo(x + radius, y);
  ctx.lineTo(x + width - radius, y);
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
  ctx.lineTo(x + width, y + height - radius);
  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
  ctx.lineTo(x + radius, y + height);
  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
  ctx.lineTo(x, y + radius);
  ctx.quadraticCurveTo(x, y, x + radius, y);
  ctx.closePath();
  if (stroke) {
    ctx.stroke();
  }
  if (fill) {
    ctx.fill();
  }
}

function getMapExporter(options) {

    function MapExporter (options) {
        this.buttonID = options.buttonID || "export_map_btn";
        this.button = $('#' + this.buttonID);
        this.mapID = options.mapID || "exported_map";
        this.mapManager = options.mapManager;
        this.auto_click = options.auto_click || false;
        this.exportedMapManager = null;
        this.timer = null;

        this.registerButton();
    }

    MapExporter.prototype.removeTimeout = function () {
        clearTimeout(this.timer);
    };

    MapExporter.prototype.registerButton = function() {
        var manager = this;
        this.button.on('click', function (e) {
            e.preventDefault();

            if ($('html').is('.ie6, .ie7, .ie8, .ie9')) {
                alert("ATTENTION!\nL'export de la cartographie n'est pas " +
                      "possible avec Internet Explorer 9 et plus ancien.\n" +
                      "Merci d'utiliser une version plus récente d'Internet " +
                      "Explorer ou un autre navigateur tel Mozilla Firefox " +
                      "ou Google Chrome.");
                return;
            }

            // make sure we launch it only once until it finishes.
            var state = $(this).attr('disabled');
            // var timer;
            var cancel = function() {
                console.log("cancelled.");
                manager.removeTimeout();
                manager.resetButton();
                manager.restoreButton();
            };
            if (state != 'disabled') {
                try {
                    manager.timer = setTimeout(cancel, 90000);
                    manager.do_export();
                } catch(exp) {
                    console.log("Error while exporting.");
                    console.log(exp.toString());
                    cancel();
                }
            }
        });
        this.restoreButton();
    };

    MapExporter.prototype.makeButtonPending = function () {
        this.button.html(' en cours…');
        this.button.attr('disabled', 'disabled');
    };

    MapExporter.prototype.restoreButton = function () {
        this.button.text('Exporter');
        this.button.removeAttr('disabled');
    };

    MapExporter.prototype.resetButton = function () {
        $('.exportbuttons .save-as-png').remove();
        $('#' + this.mapID).remove();
        $('.map-holder').append('
');
    };

    MapExporter.prototype.do_export = function() {
        console.log("Exporting map…");

        // reset button state
        this.resetButton();
        this.makeButtonPending();

        // prepare static map options
        var options = this.mapManager.export_props();
        options.static_map = true;
        options.mapID = this.mapID;

        var manager = this;
        options.onload = function (mmap) {

            function cssvalue(elem, prop) {
                return parseInt(elem.css(prop).replace('px', ''));
            }

            var map = mmap.map;
            doImage = function (err, canvas) {
                var titleSizePx = 22;
                var titleHeight = titleSizePx + Math.round(titleSizePx * 0.25);
                var subtitleSizePx = 16;
                var subtitleHeight = subtitleSizePx + Math.round(subtitleSizePx * 0.25);
                var subtitleHeightPosition = (titleHeight + (subtitleHeight - (titleSizePx / 2)));
                var textHeight = titleHeight;
                if (manager.mapManager.subtitle) {
                    textHeight += subtitleHeight;
                }

                var new_can = $('#canvas')[0];
                new_can.width = canvas.width;
                new_can.height = canvas.height + textHeight;
                var canvasWidth = new_can.width;
                var canvasHeight = new_can.height;
                var ctx = new_can.getContext("2d");
                // fill with white
                ctx.fillStyle = "rgb(255,255,255)";
                ctx.fillRect(0, 0, new_can.width, new_can.height);
                ctx.drawImage(canvas, 0, textHeight);

                // draw title
                ctx.fillStyle = "black";
                ctx.font = titleSizePx + "px 'Droid Sans',sans-serif";
                ctx.textAlign = "center";
                ctx.textBaseline = "middle";

                // draw subtitle
                ctx.fillText(manager.mapManager.title, new_can.width / 2 , (titleHeight - (titleSizePx / 2)));
                if (manager.mapManager.subtitle !== null) {
                    ctx.font = subtitleSizePx + "px 'Droid Sans',sans-serif";
                    ctx.fillText(manager.mapManager.subtitle, new_can.width / 2 , subtitleHeightPosition);
                }

                // draw scale
                var leafletScaleWidth = parseInt($('#'+ manager.mapID +' .leaflet-control-scale-line').css('width').replace('px', ''));
                var scaleHeight = 16;
                var scaleWidth = leafletScaleWidth; // 74
                var scaleLeft = 10;
                var scaleBottom = new_can.height - 10;
                var scaleColor = "#333333";
                // draw white .5 opacity rect
                ctx.fillStyle = "rgba(255,255,255, 0.5)";
                ctx.fillRect(scaleLeft, scaleBottom - scaleHeight,
                             scaleWidth, scaleHeight);
                // draw border
                ctx.strokeStyle = scaleColor;
                ctx.lineWidth = 2;
                ctx.lineJoin = 'round';
                ctx.lineCap = 'round';
                ctx.beginPath();
                ctx.moveTo(scaleLeft, scaleBottom - scaleHeight);
                ctx.lineTo(scaleLeft, scaleBottom);
                ctx.lineTo(scaleLeft + scaleWidth, scaleBottom);
                ctx.lineTo(scaleLeft + scaleWidth, scaleBottom - scaleHeight);
                ctx.stroke();
                // draw text
                var scale_text = $('#'+ manager.mapID +' .leaflet-control-scale-line').text();
                ctx.fillStyle = scaleColor;
                ctx.font = "11px 'Droid Sans',sans-serif";
                ctx.textAlign = "left";
                ctx.textBaseline = "bottom";
                ctx.fillText(scale_text, scaleLeft + 2, scaleBottom - 1);

                // draw legend
                var html_legend = $('#' + manager.mapID + ' .legend');
                if (html_legend.length) {
                    var legendWidth = cssvalue(html_legend, 'width');
                    var legendHeight = cssvalue(html_legend, 'height');
                    var legendMarginRight = cssvalue(html_legend, 'margin-right');
                    var legendMarginBottom = cssvalue(html_legend, 'margin-bottom');
                    var legendPaddingLeft = cssvalue(html_legend, 'padding-left');
                    var legendPaddingTop = cssvalue(html_legend, 'padding-top');
                    var legendX = canvasWidth - legendWidth - legendMarginRight;
                    var legendY = canvasHeight - legendHeight - legendMarginBottom;
                    ctx.fillStyle = "rgba(255,255,255, 0.8)";
                    ctx.strokeStyle = '#bbbbbb';
                    roundRect(ctx, legendX, legendY,
                              legendWidth, legendHeight, 5, true, true);
                    // draw legend text
                    ctx.shadowOffsetX = 0;
                    ctx.shadowOffsetY = 0;
                    ctx.shadowBlur = 0;
                    var legendTextX = legendX + legendPaddingLeft;
                    var legendTextY = legendY + legendPaddingTop;
                    var currentLegendTextY = legendTextY;
                    html_legend.children('span').each(function (index, spanElem) {
                        var span = $(spanElem);
                        var i = span.children('i');
                        var width = cssvalue(i, 'width');
                        var height = cssvalue(i, 'height');
                        var text = span.text();
                        ctx.fillStyle = i.css('background-color');
                        ctx.fillRect(legendTextX, currentLegendTextY,
                                      width, height);
                        // text
                        ctx.fillStyle = scaleColor;
                        ctx.font = "12px 'Droid Sans',sans-serif";
                        ctx.textAlign = "left";
                        ctx.textBaseline = "middle";
                        ctx.fillText(text,
                                     legendTextX + width,
                                     currentLegendTextY + height / 2);
                        currentLegendTextY += height;
                    });
                }

                // draw HC legend
                var html_hc_legend = $('#' + manager.mapID + ' .hc_legend');
                if (html_hc_legend.length) {
                    var hcLegendWidth = cssvalue(html_hc_legend, 'width');
                    var hcLegendHeight = cssvalue(html_hc_legend, 'height');
                    var hcLegendMarginLeft = cssvalue(html_hc_legend, 'margin-left');
                    var hcLegendMarginTop = cssvalue(html_hc_legend, 'margin-top');
                    var hcLegendPaddingLeft = cssvalue(html_hc_legend, 'padding-left');
                    var hcLegendPaddingTop = cssvalue(html_hc_legend, 'padding-top');
                    var hcLegendX = hcLegendMarginLeft;
                    var hcLegendY = hcLegendMarginTop + textHeight;
                    ctx.strokeStyle = '#bbbbbb';
                    ctx.fillStyle = "rgba(255,255,255, 0.8)";
                    ctx.shadowOffsetX = 0;
                    ctx.shadowOffsetY = 0;
                    ctx.shadowBlur = 0;
                    ctx.shadowColor = scaleColor;
                    roundRect(ctx, hcLegendX, hcLegendY,
                              hcLegendWidth, hcLegendHeight, 5, true, true);
                    var currentHcLegendTextY = hcLegendY + hcLegendPaddingTop;
                    var oddColor = "rgba(33,33,33, 0.1)";
                    var evenColor = "rgba(255,255,255, 0.8)";
                    $('.hc_line').each(function (index, spanElem) {
                        var span = $(spanElem);
                        var width = cssvalue(span, 'width');
                        var height = 10; //cssvalue(span, 'height');
                        height -= 1;
                        var text = span.text();
                        // text
                        ctx.fillStyle = (index % 2 === 0) ? null : oddColor;
                        if (index % 2 !== 0) {
                            ctx.fillRect(hcLegendX, currentHcLegendTextY,
                                          hcLegendWidth, height);
                        }
                        ctx.fillStyle = scaleColor;
                        ctx.font = "9px droid_sans_monoregular";
                        ctx.textAlign = "left";
                        ctx.textBaseline = "middle";
                        ctx.fillText(text,
                                     hcLegendX + hcLegendPaddingLeft,
                                     currentHcLegendTextY + height / 2);
                        currentHcLegendTextY += height;
                    });
                }

                console.log("done doImage");

                var url = new_can.toDataURL();
                var link = $('');
                link.attr('href', url);
                link.attr('download', 'exported_map.png');
                link.attr('class', 'save-as-png pure-button');
                link.html('');
                link.attr('title', "Enregistrer l'image PNG");
                $('.exportbuttons').append(link);

                // remove map
                $('#' + manager.mapID).remove();

                // toggle back
                manager.restoreButton();

                // emulate a click on the created button to popup save dialog
                if (manager.auto_click === true) {
                    var e = document.createEvent("MouseEvents");
                    e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
                                     false, false, false, false, 0, null);
                    link[0].dispatchEvent(e);
                }

                manager.removeTimeout();
            };

            // wait 2s between map creation and exporting to canvas
            // to allow any animation to complete
            var interval;
            interval = setInterval(function (){
                clearInterval(interval);
                leafletImage(map, doImage);
            }, 2000);

        };
        this.exportedMapManager = getMalariaMapManager(options);

    };
    return new MapExporter(options);
}


text:
package main

import "github.com/mackerelio/go-check-plugins/check-uptime/lib"

func main() {
	checkuptime.Do()
}

redpajama_set_name: RedPajamaGithub


text:
package com.lizy.myglide.load.engine.cache;

import android.support.annotation.Nullable;

import com.lizy.myglide.load.Key;

import java.io.File;

/**
 * Created by lizy on 16-5-5.
 */
public class DiskCacheAdapter implements DiskCache {
    @Nullable
    @Override
    public File get(Key k) {
        return null;
    }

    @Override
    public void put(Key k, Writer writer) {

    }

    @Override
    public void delete(Key k) {

    }

    @Override
    public void clear() {

    }
}


text:
/*
 *	Name:		Hacker News OnePage
 *	Version:	0.9.1 Beta
 *  Author:		Tim Dupree
 *				http://www.tdupree.com
 *				email: tim [AT] tdupree [DOT] com
 *
 *	License:	Hacker News OnePage is released under the Open Source MIT License
 *				(c) 2009 Tim Dupree
 *
 *	Original Creation Date:		July 24, 2008
 *  Ported from Greasemonkey to Chrome:   June 1, 2009
 *  Version 0.9.1 Date: March 13, 2013
 *
 *	Summary:	Provides users with the ability to browse Hacker News articles and comments without leaving the page.
 *				This is pretty much the same as the greasemonkey version, just unsafeWindow has been changed to
 *				contentWindow and I leave the table based article header in rather than replacing it with the
 *				CSS styled div based article header.  The div version deals with the resize better, but there
 *				was a problem appending it to the DOM, so I commented that line out.
 *
 */

	// Change these iFrame defaults if you wish to tweak the height
	// and width of the article and comments viewports
	var iFrameHeight = "93%";
	var iFrameWidth = "100%";

	// default bg Highlight Color displayed for any visisted articles/comments
	var highlight = "#FFE4CF";

	/* remove the co2stats js and html
	 * for some reason, the co2stats js completely breaks HN OnePage
	 * this is a rather crummy fix as we must rely on dom indexes that
	 * could easily change since we are working with a lack of element ID's

	// first we bank on the footer being in the last 'center' tag
	var centers = document.getElementsByTagName('center');
	var children = centers[centers.length - 1].childNodes;
	var cleaned = 0;
	var childrenLength = children.length - 1;

	// now we bet that the co2stats will be at the end of the footer
	// thus we itereate from the last element to the first to hit the
	// co2stat elements and remove them without accidentally removing other elements
	for(var i = childrenLength; i > 0; i--){
		if(children[i].nodeName == "SCRIPT" || children[i].nodeName == "A"){
			centers[centers.length - 1].removeChild(children[i]);
			cleaned++;
			if(cleaned >= childrenLength){
				i = 0; //break from search after removing the co2stats script and anchor elements
			}
		}
	}
	*/

	/* Add jQuery
	 * This "add jQuery" code is necessary for the geasemonkey version,
	 * but we package jquery-1.3.2.min.js with the chrome extension instead.
	 */
	//var GM_JQ = document.createElement('script');
	//GM_JQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js';
	//GM_JQ.type = 'text/javascript';
	//document.getElementsByTagName('head')[0].appendChild(GM_JQ);

	// Check if jQuery's loaded
	//function GM_wait() {
	//	if(typeof contentWindow.jQuery == 'undefined') { window.setTimeout(GM_wait,100); }
	//else { $ = contentWindow.jQuery; letsJQuery(); }
	//}
	//GM_wait();

	// Let the Fun Begin
	function letsJQuery() {
		// The following html is left uncondensed so that others may better follow/modify it
		var accordian = '
' +
					'
Comments

' +
					'
Article

' +
    			'
';
		var loginURL = $("a:eq(7)").attr("href");
		var header = '
' +
			'
' +
				'' +
					'' +
				'' +
			'
' +
			'
' +
				'
' +
					'Hacker News' +
				'
' +
				'
' +
					'new | ' +
					'comments | ' +
					'leaders | ' +
					'jobs | ' +
					'submit' +
				'
' +
			'
' +
			'
' + $("tr:eq(1) td:eq(2)").html() + '
' +
		'
';

		// avoid modifying the comments and login pages when adding
		// the new UI by not modifying pages with forms
		var hasForm = $("body").find("form");
		if(hasForm.length <= 1){
			$("center:eq(0)").wrap("

");
			$("center:eq(0)").replaceWith($("center:eq(0)").html());
			//$("tr:eq(1)").replaceWith("
" + header + "
");
			$("table:eq(0)").attr("width", "100%");
			$("#news_column").after(accordian);

			// add the co2stats image and link back to the page footer,
			// basically everything is the same as before except that
			// it opens in new page rather than a popup
			//$("center:last").append("

");
		}

		// build object arrays containing the article title links and comments links
		var articleComments = $(".subtext a:last-child");
		var articleURL = $("a:first", ".title");

		// add click function to title links to open them in the article pane
		$("a:first", ".title").each(function(i){
			if($(this).text() != "More"){
				$(this).click(function(event){
					event.preventDefault();
					$(this).css("background", highlight);
					$("#iArticle").attr("src", articleURL[i]);
					$.ajax({
						url: articleComments[i],
						dataType: 'html',
						complete: function(jqXHR, textStatus){
							$("#iComments").contents().find('html').html(jqXHR.responseText);
						}
					});
					$("#commentsToggle.toggler").next().hide(180);
					$("#articleToggle.toggler").next().show(180);
					window.scrollTo(0,0);

				});
			}
		});

		// add click function to comments links to open them in the comments pane
		$(".subtext a:last-child").each(function(i){
			$(this).click(function(event){
				event.preventDefault();
				$(this).css("background", highlight);
				$("#iArticle").attr("src", articleURL[i]);
				$.ajax({
					url: articleComments[i],
					dataType: 'html',
					complete: function(jqXHR, textStatus){
						$("#iComments").contents().find('html').html(jqXHR.responseText);
					}
				});
				$("#articleToggle.toggler").next().hide(180);
				$("#commentsToggle.toggler").next().show(180);
				window.scrollTo(0,0);

			});
		});

		// enable the toggle properties of the comments and article panes
		$(".toggler").click(function() {
			$(this).next().toggle(180);
		}).next().hide();

		// add height and width properties to iFrames
		$("iFrame").css("width", iFrameWidth);
		$("iFrame").css("height", iFrameHeight);

		//add the css
		var css = '';

		//old css (whole page scrolls vertically as opposed to just the news section)
		//un-comment the line below (and comment the "var css" line above) if you liked the old style of Hacker News OnePage better
		//var css = '';

		$(css).appendTo("head")
	}
	letsJQuery();


text:
from gluon import current

# Parameters for job queues.
REPUTATION_SYSTEM_QUEUE = 'repsys-queue'
REPUTATION_SYSTEM_RUN_URL = '/crowdgrader/queues/run_rep_sys/'
REPUTATION_SYSTEM_PARAM_NUM_ITERATIONS = 'n_iterations'
REPUTATION_SYSTEM_PARAM_VENUE_ID = 'venue_id'
REPUTATION_SYSTEM_PARAM_REVIEW_PERCENTAGE = 'review_percentage'
REPUTATION_SYSTEM_STARTOVER = 'startover'
REPUTATION_SYSTEM_ALGO = 'algo'
REPUTATION_SYSTEM_RUN_ID = 'run_id'
REPUTATION_SYSTEM_PUBLISH = 'publish'
# Below are the options for convex optimization.
REPUTATION_SYSTEM_COST_TYPE = 'cost_type'
REPUTATION_SYSTEM_POS_SLOPE = 'pos_slope'
REPUTATION_SYSTEM_NEG_SLOPE = 'neg_slope'
REPUTATION_SYSTEM_NORMALIZE_GRADES = 'normalize_grades'
REPUTATION_SYSTEM_NORMALIZATION_SCALE = 'normalization_scale'
REPUTATION_SYSTEM_NORMALIZE_EACH_ITER = 'normalize_each_iteration'
REPUTATION_SYSTEM_USE_SUBMISSION_RANK_IN_REP = 'use_rank_in_rep'
REPUTATION_SYSTEM_SUBMISSION_RANK_REP_EXP = 'rank_rep_exp'
REPUTATION_SYSTEM_REPUTATION_METHOD = 'reputation_method'
REPUTATION_SYSTEM_PREC_COEFF = 'prec_coeff'
REPUTATION_SYSTEM_PREC_METHOD = 'prec_method'
# Below are the options for Vancouver.
REPUTATION_SYSTEM_DO_DEBIAS = 'do_debias'
REPUTATION_SYSTEM_USE_MEDIAN = 'use_median'
REPUTATION_SYSTEM_USE_REPUTATION = 'use_reputation'

# Makes the above available to modules.
current.REPUTATION_SYSTEM_QUEUE = REPUTATION_SYSTEM_QUEUE
current.REPUTATION_SYSTEM_RUN_URL = REPUTATION_SYSTEM_RUN_URL
current.REPUTATION_SYSTEM_PARAM_NUM_ITERATIONS = REPUTATION_SYSTEM_PARAM_NUM_ITERATIONS
current.REPUTATION_SYSTEM_PARAM_VENUE_ID = REPUTATION_SYSTEM_PARAM_VENUE_ID
current.REPUTATION_SYSTEM_PARAM_REVIEW_PERCENTAGE = REPUTATION_SYSTEM_PARAM_REVIEW_PERCENTAGE
current.REPUTATION_SYSTEM_STARTOVER = REPUTATION_SYSTEM_STARTOVER
current.REPUTATION_SYSTEM_ALGO = REPUTATION_SYSTEM_ALGO
current.REPUTATION_SYSTEM_RUN_ID = REPUTATION_SYSTEM_RUN_ID
current.REPUTATION_SYSTEM_PUBLISH = REPUTATION_SYSTEM_PUBLISH
current.REPUTATION_SYSTEM_COST_TYPE = REPUTATION_SYSTEM_COST_TYPE
current.REPUTATION_SYSTEM_POS_SLOPE = REPUTATION_SYSTEM_POS_SLOPE
current.REPUTATION_SYSTEM_NEG_SLOPE = REPUTATION_SYSTEM_NEG_SLOPE
current.REPUTATION_SYSTEM_NORMALIZE_GRADES = REPUTATION_SYSTEM_NORMALIZE_GRADES
current.REPUTATION_SYSTEM_NORMALIZATION_SCALE = REPUTATION_SYSTEM_NORMALIZATION_SCALE
current.REPUTATION_SYSTEM_NORMALIZE_EACH_ITER = REPUTATION_SYSTEM_NORMALIZE_EACH_ITER
current.REPUTATION_SYSTEM_USE_SUBMISSION_RANK_IN_REP = REPUTATION_SYSTEM_USE_SUBMISSION_RANK_IN_REP
current.REPUTATION_SYSTEM_SUBMISSION_RANK_REP_EXP = REPUTATION_SYSTEM_SUBMISSION_RANK_REP_EXP
current.REPUTATION_SYSTEM_REPUTATION_METHOD = REPUTATION_SYSTEM_REPUTATION_METHOD
current.REPUTATION_SYSTEM_PREC_COEFF = REPUTATION_SYSTEM_PREC_COEFF
current.REPUTATION_SYSTEM_PREC_METHOD = REPUTATION_SYSTEM_PREC_METHOD
current.REPUTATION_SYSTEM_DO_DEBIAS = REPUTATION_SYSTEM_DO_DEBIAS
current.REPUTATION_SYSTEM_USE_MEDIAN = REPUTATION_SYSTEM_USE_MEDIAN
current.REPUTATION_SYSTEM_USE_REPUTATION = REPUTATION_SYSTEM_USE_REPUTATION

# Algorithm names
ALGO_OPT = 'opt'
ALGO_DISTR = 'distr'
ALGO_VANCOUVER = 'vancouver'
ALGO_DISTR_NOREP = 'distr'
ALGO_LIST = [ALGO_OPT, ALGO_DISTR, ALGO_VANCOUVER]
ALGO_DEFAULT = ALGO_VANCOUVER
ALGO_PREC_METHOD_DIST = 'stdev'
ALGO_PREC_METHOD_CORR = 'corr'
current.ALGO_PREC_METHOD_DIST = ALGO_PREC_METHOD_DIST
current.ALGO_PREC_METHOD_CORR = ALGO_PREC_METHOD_CORR
# Type of matrix D
REPUTATION_SYSTEM_MATRIX_D_TYPE = "matrix_D_type"
MATRIX_D_TYPE_GRADES_DIST = "distance_between_grades"
MATRIX_D_TYPE_GRADES_SINGLE = "single_grades"
current.MATRIX_D_TYPE_GRADES_DIST = MATRIX_D_TYPE_GRADES_DIST
current.MATRIX_D_TYPE_GRADES_SINGLE = MATRIX_D_TYPE_GRADES_SINGLE

# Algo defaults
ALGO_DEFAULT_COST_TYPE = 'linear'
ALGO_DEFAULT_POS_SLOPE = 1.0
ALGO_DEFAULT_NEG_SLOPE = 4.0
ALGO_DEFAULT_NUM_ITERATIONS = 10
ALGO_DEFAULT_NORMALIZE = True
ALGO_DEFAULT_NORMALIZATION_SCALE = 1.0
ALGO_DEFAULT_REVIEWS_AS_PERCENTAGE = 25.0
current.ALGO_DEFAULT_REVIEWS_AS_PERCENTAGE = ALGO_DEFAULT_REVIEWS_AS_PERCENTAGE
ALGO_DEFAULT_USE_RANK_IN_REPUTATION = True
ALGO_DEFAULT_RANK_REP_EXP = 0.7
ALGO_DEFAULT_PREC_COEFF = 1.0
ALGO_DEFAULT_REPUTATION_METHOD = 'cost'
ALGO_DEFAULT_PREC_METHOD = 'stdev'
# Vancouver.
ALGO_DEFAULT_DO_DEBIAS = False
ALGO_DEFAULT_USE_MEDIAN = False
ALGO_DEFAULT_USE_REPUTATION = True


text:
module RocketJobMissionControl
  # The authorization callback
  module Config
    mattr_accessor :authorization_callback
  end

  class Engine < ::Rails::Engine
    isolate_namespace RocketJobMissionControl

    require "rocketjob"
    require "jquery-rails"
    require "sass-rails"
    require "access-granted"
    begin
      require "rocketjob_enterprise"
    rescue LoadError
    end

    config.rocket_job_mission_control = ::RocketJobMissionControl::Config

    config.to_prepare do
      Rails.application.config.assets.precompile += %w[
        rocket_job_mission_control/rocket-icon-64x64.png
      ]
    end
  end
end


text:
<?php

namespace app\models;
use Yii;
use yii\data\ActiveDataProvider;

class UsersSearch extends \yii\base\Model
{
    public $fullName;

    public function rules() {
        return [
            [['fullName'], 'safe']
        ];
    }

    public function search($params) {
        $query = Users::find();
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => ['pageSize' => 10]
        ]);

        $dataProvider->setSort([
            'attributes' => [
                'fullName' => [
                    'asc' => ['username' => SORT_ASC, 'first_name' => SORT_ASC, 'last_name' => SORT_ASC, ],
                    'desc' => ['username' => SORT_DESC, 'first_name' => SORT_DESC, 'last_name' => SORT_DESC, ],
                    'default' => SORT_ASC
                ],
            ]
        ]);

        if (!($this->load($params) && $this->validate())) {
            return $dataProvider;
        }

        $query->andWhere('first_name LIKE "%' . $this->fullName . '%" ' .
            'OR last_name LIKE "%' . $this->fullName . '%" ' .
            'OR username LIKE "%' . $this->fullName . '%" '
        );

        return $dataProvider;
    }
}


text:
package com.ip_b1.fii.admission.DTO;

public class FormStatusEntity {

    private String CNP;
    private String status;

    public FormStatusEntity(String CNP, String status) {
        this.CNP = CNP;
        this.status = status;
    }

    public String getCNP() {
        return CNP;
    }

    public void setCNP(String CNP) {
        this.CNP = CNP;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}


text:
About
=====

This is a LuaJIT FFI-based binding to the [nanomsg library](http://nanomsg.org).

It exposes the raw API, as well as a higher-level convenience layer.

Installation
============

First, make sure that the [nanomsg](https://github.com/250bpm/nanomsg)
shared library is available on your `LD_LIBRARY_PATH`.

Then, you can either:

- simply put [nanomsg-ffi.lua](https://github.com/nanomsg/luajit-nanomsg/blob/master/nanomsg-ffi.lua) somewhere on your `LUA_PATH`;
- clone this repository and run `make install`;
- install the latest release with the [LuaRocks](http://luarocks.org/) package manager:

        luarocks install "https://raw.github.com/nanomsg/luajit-nanomsg/master/rockspec/luajit-nanomsg-scm-1.rockspec"

Usage
=====

```lua
local nn = require 'nanomsg-ffi'

-- nn.C exposes all of the nanomsg C API functions
print( nn.C.nn_errno() )

-- But there is a friendlier API available directly from nn:
print( nn.errno() )
print( nn.EAGAIN )

-- For convenience, names for errno's are available in nn.E
assert( nn.E[ nn.EAGAIN ] == 'EAGAIN' )

-- Use the nn.socket class rather than the functions in nn.C
local req, id, rc, err

req, err = nn.socket( nn.REQ )
assert( req, nn.strerror(err) )

id, err = req:connect( "tcp://127.0.0.1:555" )
assert( id, nn.strerror(err) )

local msg = "hello world"
rc, err = req:send( msg, #msg )
assert( rc > 0, nn.strerror(err) )

```

Socket object
=============

Socket is nanomsg's primary object.  Socket object can instantiated with `nn.socket( protocol, options)`, where `protocol` is the nanomsg enum, such as `nn.SUB`, and `options` is a table with the following optional fields:

 * `close_on_gc`:  Default is true.  When true, the socket's `close` method will be invoked upon garbage collection.  `close` may block, so one may to wish to invoke it manually at a determined time.

 * `domain`:  Default is `nn.AF_SP`.  The domain of the socket.  Options are `nn.AF_SP` and `nn.AF_SP_RAW`.

TODO: generate LDoc documentation and link to it

Running the test suite
======================

Test require [cwtest](https://github.com/catwell/cwtest). Either install it on your
system or just put [cwtest.lua](https://github.com/catwell/cwtest/blob/master/cwtest.lua)
somewhere on your LUA_PATH, then run `make test`.

Other nanomsg Lua Bindings
==========================

If you are looking for a nanomsg binding that can work with plain Lua,
as well as LuaJIT, check out [lua-nanomsg](https://github.com/Neopallium/lua-nanomsg).

Roadmap
=======

This is usable now.   The future holds:

 * more documentation
 * more examples and performance tests
 * more hand-holding classes for nanomsg concepts
 * bind nn_sendmsg and nn_recvmsg and associated control structures

License
=======

```
Copyright (c) 2013 Evan Wies <evan at neomantra dot net>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
```


text:
@interface MFCustomEventFullscreen : NSObject

- (void)loadFullscreenWithOptionalParameters:(NSString *)optionalParameters trackingPixel:(NSString *)trackingPixel;

- (void)showFullscreenFromRootViewController:(UIViewController *)rootViewController;

- (void)notifyAdFailed;

- (void)notifyAdLoaded;

- (void)notifyAdWillAppear;

- (void)notifyAdWillClose;

- (void)notifyAdWillLeaveApplication;

- (void)finish;

@property (nonatomic, assign) id<MFCustomEventFullscreenDelegate> delegate;
@property (nonatomic, retain) NSString* trackingPixel;

@end


text:
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ChangeListManager">
    <list default="true" id="f501869b-8786-41c3-a818-40bfcd1c8acb" name="Default" comment="">
      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/index.html" afterPath="$PROJECT_DIR$/index.html" />
      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
    </list>
    <ignored path="landing.iws" />
    <ignored path=".idea/workspace.xml" />
    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
    <option name="TRACKING_ENABLED" value="true" />
    <option name="SHOW_DIALOG" value="false" />
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
    <option name="LAST_RESOLUTION" value="IGNORE" />
  </component>
  <component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
  <component name="CreatePatchCommitExecutor">
    <option name="PATCH_PATH" value="" />
  </component>
  <component name="DaemonCodeAnalyzer">
    <disable_hints />
  </component>
  <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
  <component name="FavoritesManager">
    <favorites_list name="landing" />
  </component>
  <component name="FileEditorManager">
    <leaf>
      <file leaf-file-name="index.html" pinned="false" current-in-tab="true">
        <entry file="file://$PROJECT_DIR$/index.html">
          <provider selected="true" editor-type-id="text-editor">
            <state vertical-scroll-proportion="0.6064815" vertical-offset="2319" max-vertical-offset="5550">
              <caret line="207" column="67" selection-start-line="207" selection-start-column="67" selection-end-line="207" selection-end-column="67" />
              <folding>
                <element signature="n#style#0;n#img#0;n#div#0;n#div#0;n#div#0;n#section#1;n#body#0;n#html#0;n#!!top" expanded="true" />
                <element signature="n#style#0;n#img#0;n#a#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
                <element signature="n#style#0;n#img#0;n#div#0;n#noscript#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
                <element signature="n#style#0;n#p#0;n#div#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
              </folding>
            </state>
          </provider>
        </entry>
      </file>
    </leaf>
  </component>
  <component name="Git.Settings">
    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
  </component>
  <component name="IdeDocumentHistory">
    <option name="CHANGED_PATHS">
      <list>
        <option value="$PROJECT_DIR$/css/bootstrap.css" />
        <option value="$PROJECT_DIR$/license.html" />
        <option value="$PROJECT_DIR$/js/validate.js" />
        <option value="$PROJECT_DIR$/index.html" />
      </list>
    </option>
  </component>
  <component name="JsGulpfileManager">
    <detection-done>true</detection-done>
  </component>
  <component name="ProjectFrameBounds">
    <option name="x" value="8" />
    <option name="y" value="23" />
    <option name="width" value="2556" />
    <option name="height" value="1417" />
  </component>
  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
    <OptionsSetting value="true" id="Add" />
    <OptionsSetting value="true" id="Remove" />
    <OptionsSetting value="true" id="Checkout" />
    <OptionsSetting value="true" id="Update" />
    <OptionsSetting value="true" id="Status" />
    <OptionsSetting value="true" id="Edit" />
    <ConfirmationsSetting value="2" id="Add" />
    <ConfirmationsSetting value="0" id="Remove" />
  </component>
  <component name="ProjectView">
    <navigator currentView="ProjectPane" proportions="" version="1">
      <flattenPackages />
      <showMembers />
      <showModules />
      <showLibraryContents />
      <hideEmptyPackages />
      <abbreviatePackageNames />
      <autoscrollToSource />
      <autoscrollFromSource />
      <sortByType />
    </navigator>
    <panes>
      <pane id="ProjectPane">
        <subPane>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="landing" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
          </PATH>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="landing" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="landing" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
          </PATH>
          <PATH>
            <PATH_ELEMENT>
              <option name="myItemId" value="landing" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="landing" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
            <PATH_ELEMENT>
              <option name="myItemId" value="js" />
              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
            </PATH_ELEMENT>
          </PATH>
        </subPane>
      </pane>
      <pane id="Scope">
        <subPane subId="Problems" />
        <subPane subId="Project Files" />
      </pane>
    </panes>
  </component>
  <component name="PropertiesComponent">
    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
    <property name="WebServerToolWindowFactoryState" value="false" />
    <property name="HbShouldOpenHtmlAsHb" value="" />
    <property name="FullScreen" value="false" />
  </component>
  <component name="RecentsManager">
    <key name="CopyFile.RECENT_KEYS">
      <recent name="$PROJECT_DIR$/img" />
    </key>
    <key name="MoveFile.RECENT_KEYS">
      <recent name="$PROJECT_DIR$/css" />
      <recent name="$PROJECT_DIR$/js" />
      <recent name="$PROJECT_DIR$" />
    </key>
  </component>
  <component name="RunManager">
    <configuration default="true" type="DartUnitRunConfigurationType" factoryName="DartUnit">
      <method />
    </configuration>
    <configuration default="true" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application">
      <method />
    </configuration>
    <configuration default="true" type="JSTestDriver:ConfigurationType" factoryName="JsTestDriver">
      <setting name="configLocationType" value="CONFIG_FILE" />
      <setting name="settingsFile" value="" />
      <setting name="serverType" value="INTERNAL" />
      <setting name="preferredDebugBrowser" value="Chrome" />
      <method />
    </configuration>
    <configuration default="true" type="JavaScriptTestRunnerKarma" factoryName="Karma" config-file="">
      <envs />
      <method />
    </configuration>
    <configuration default="true" type="JavascriptDebugType" factoryName="JavaScript Debug">
      <method />
    </configuration>
    <configuration default="true" type="NodeJSConfigurationType" factoryName="Node.js" working-dir="">
      <method />
    </configuration>
    <configuration default="true" type="cucumber.js" factoryName="Cucumber.js">
      <option name="cucumberJsArguments" value="" />
      <option name="executablePath" />
      <option name="filePath" />
      <method />
    </configuration>
    <configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
      <node-options />
      <gulpfile />
      <tasks />
      <pass-parent-envs>true</pass-parent-envs>
      <envs />
      <method />
    </configuration>
    <list size="0" />
  </component>
  <component name="ShelveChangesManager" show_recycled="false" />
  <component name="SvnConfiguration">
    <configuration />
  </component>
  <component name="TaskManager">
    <task active="true" id="Default" summary="Default task">
      <changelist id="f501869b-8786-41c3-a818-40bfcd1c8acb" name="Default" comment="" />
      <created>1427140593862</created>
      <option name="number" value="Default" />
      <updated>1427140593862</updated>
    </task>
    <servers />
  </component>
  <component name="ToolWindowManager">
    <frame x="8" y="23" width="2556" height="1417" extended-state="0" />
    <editor active="true" />
    <layout>
      <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
      <window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.051643193" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
      <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
      <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
      <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
      <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
      <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
    </layout>
  </component>
  <component name="Vcs.Log.UiProperties">
    <option name="RECENTLY_FILTERED_USER_GROUPS">
      <collection />
    </option>
    <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
      <collection />
    </option>
  </component>
  <component name="VcsContentAnnotationSettings">
    <option name="myLimit" value="2678400000" />
  </component>
  <component name="VcsManagerConfiguration">
    <option name="myTodoPanelSettings">
      <TodoPanelSettings />
    </option>
  </component>
  <component name="XDebuggerManager">
    <breakpoint-manager />
    <watches-manager />
  </component>
  <component name="editorHistoryManager">
    <entry file="file://$PROJECT_DIR$/index.html">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1200">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding>
            <element signature="n#style#0;n#img#0;n#div#0;n#div#0;n#div#0;n#section#1;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#a#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#div#0;n#noscript#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#p#0;n#div#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/index.html">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="5325">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding>
            <element signature="n#style#0;n#img#0;n#div#0;n#div#0;n#div#0;n#section#1;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#a#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#div#0;n#noscript#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#p#0;n#div#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/.idea/scopes/scope_settings.xml">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="150">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/index.html">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="1399" max-vertical-offset="4710">
          <caret line="109" column="16" selection-start-line="109" selection-start-column="16" selection-end-line="109" selection-end-column="16" />
          <folding>
            <element signature="n#style#0;n#img#0;n#div#0;n#div#0;n#div#0;n#section#1;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#a#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#div#0;n#noscript#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#p#0;n#div#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/.idea/scopes/scope_settings.xml">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="150">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/index.html">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="4170">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
          <folding>
            <element signature="n#style#0;n#img#0;n#div#0;n#div#0;n#div#0;n#section#1;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#a#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#div#0;n#noscript#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#p#0;n#div#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/.idea/scopes/scope_settings.xml">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1303">
          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/index.html">
      <provider selected="true" editor-type-id="text-editor">
        <state vertical-scroll-proportion="0.6064815" vertical-offset="2319" max-vertical-offset="5550">
          <caret line="207" column="67" selection-start-line="207" selection-start-column="67" selection-end-line="207" selection-end-column="67" />
          <folding>
            <element signature="n#style#0;n#img#0;n#div#0;n#div#0;n#div#0;n#section#1;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#a#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#img#0;n#div#0;n#noscript#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
            <element signature="n#style#0;n#p#0;n#div#0;n#div#0;n#section#4;n#body#0;n#html#0;n#!!top" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
  </component>
</project>


text:
//
//  BBTooltipViewControllerDataSource.h
//  BBFrameworks
//
//  Created by Willam Towe on 6/17/15.
//  Copyright (c) 2015 Bion Bilateral, LLC. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//
//  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#import <Foundation/Foundation.h>

@class BBTooltipViewController;

/**
 Protocol for the BBTooltipViewController data source.
 */
@protocol BBTooltipViewControllerDataSource <NSObject>
@required
/**
 Return the number of tooltips that will be displayed by the provided tooltip view controller.

 @param viewController The tooltip view controller that sent the message
 @return The number of tooltips to display
 */
- (NSInteger)numberOfTooltipsForTooltipViewController:(BBTooltipViewController *)viewController;
/**
 Return the view the tooltip at the provided index should be attached to.

 @param viewController The tooltip view controller that sent the message
 @param index The index of the tooltip
 @return The attachment view for the tooltip
 */
- (UIView *)tooltipViewController:(BBTooltipViewController *)viewController attachmentViewForTooltipAtIndex:(NSInteger)index;
@optional
/**
 Return the text for the tooltip at the provided index.

 @param viewController The tooltip view controller that sent the message
 @param index The index of the tooltip
 @return The text for the tooltip
 */
- (NSString *)tooltipViewController:(BBTooltipViewController *)viewController textForTooltipAtIndex:(NSInteger)index;
/**
 Return the attributed text for the tooltip at the provided index.

 If this method is implemented and returns a non-zero length attributed string, it is preferred over `-[self tooltipViewController:textForTooltipAtIndex:]`.

 @param viewController The tooltip view controller that sent the message
 @param index The index of the tooltip
 @return The attributed text for the tooltip
 */
- (NSAttributedString *)tooltipViewController:(BBTooltipViewController *)viewController attributedTextForTooltipAtIndex:(NSInteger)index;
@end


text:
<document xmlns="http://maven.apache.org/changes/1.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd">
	<properties>
		<title>Project Changes</title>
		<author email="programming@wandrell.com">Bernardo Martínez Garrido</author>
	</properties>
	<body>
		<release version="0.1.0" date="2015-08-12" description="First release">
			<action dev="bmg" type="update">
				First release of the library.
			</action>
		</release>
		<release version="0.1.1" date="2015-10-16" description="Maven Site Skin">
			<action dev="bmg" type="update">
				Updated the Maven Site Skin.
			</action>
		</release>
	</body>
</document>