<commit_before>
var xhr_reqs = [];

function create_autocomplete_item(item, content_type, multiple_status, field_name){
	var field = { multiple:multiple_status, contenttype: content_type, name: field_name, value: item._id };
	var newel = _.template($('#field-autocomplete-item').html(), { title:item.title, field: field, item:item});
	return newel;
}

function update_content(data) {
	var results_data=_.template($('#'+data.template).html(), data);
	$('#'+data.element).html(results_data);
}

$(function() {
	$(".result_container div a.close").live('click', function(){
		$(this).parent().remove();
	});

	$('
Word count:

').insertAfter(".wordcount");

	$(".wordcount").keyup(function() {
		get_wordcount($(this));
	});

	$(".wordcount").each(function() {
		get_wordcount($(this));
	});

	$(".remover").live("click", function() { //Not sure if this is still used?
		$(this).parent().remove();
		return false;
	});

	$(document).on('keydown', '.datetime_hour', function(e) {
		var key = e.keyCode;
		if ((key > 33) && (key < 47)) {
			return false;
		}
		if ((key > 58) && (key < 126)) {
			return false;
		}
	});

	$(document).on('blur', '.datetime_hour', function() {
		var v = 0;
		if (($(this).val())) {
			v = Number($(this).val());
			$(this).val(leadingZeros(v));
			if ($(this).val().length > 2) {
				var s = $(this).val();
				$(this).val(s.substring(s.length - 2, s.length));
				v = parseInt($(this).val());
			}
			if (v > 23) {
				$(this).val("23");
			}
		} else {
			$(this).val("00");
		}
		if (!isFinite($(this).val())) {
			$(this).val("00");
		}
	});

	$(document).on('blur', '.datetime_minute', function() {
		if ($(this).val()) {
			var v = Number($(this).val());
			$(this).val(leadingZeros(v));
			if ($(this).val().length > 2) {
				var s = $(this).val();
				$(this).val(s.substring(s.length - 2, s.length));
				v = parseInt($(this).val());
			}
			if (v > 59) {
				$(this).val("59");
			}
		} else {
			$(this).val("00");
		}
		if (!isFinite($(this).val())) {
			$(this).val("00");
		}
	});

	$(document).on('keydown', '.datetime_minute', function(e) {
		var key = e.keyCode;
		if ((key > 33) && (key < 47)) {
			return false;
		}
		if ((key > 58) && (key < 126)) {
			return false;
		}
	});

	$(document).on('keyup', '.datetime_change', function() {
		updateDateTime(this);
	});

	$(document).on('change', '.datetime_change', function() {
		updateDateTime(this);
	});

	function updateDateTime(sender) {
		var parent = $(sender).parent();
		var val = "";
		val += parent.children('.datetime_date').val();
		val += " ";
		val += (parent.children('.datetime_hour').val()) ? parent.children('.datetime_hour').val() : "00";
		val += ":";
		val += (parent.children('.datetime_minute').val()) ? parent.children('.datetime_minute').val() : "00";
		$(sender).siblings(':hidden').val(stringToDate(val));
	}

	$(document).on('click', '.deepsearch-search', function() {
		var multiple_status = $(this).prev().attr('multiple');
		var field_name = $(this).prev().attr('fieldname');
		var searchel=$(this).prev();
		var origel = this;
		var search=$(this).prev().val();
		var content_type=$(this).prev().attr("contenttype");
		var optionel=$(this).parent().siblings('.deepsearch-options');
		var resultel=$(this).parent().siblings('.deepsearch-results');
		var indicator = $(this);
		while(xhr_reqs.length>0) {
			jqXHR=xhr_reqs.pop();
			jqXHR.abort();
		}
		indicator.html("Searching...");
		xhr_reqs.push(
			$.getJSON("/api/content", { search: search, content_type: content_type, limit: 20, fields: ["_id", "title"], order_by: "last_modified" }, function(data) {
				var pos = $.extend({}, searchel.offset(), {
		    		height: origel.offsetHeight
				});

				optionel.css({
					top: pos.top + pos.height
					, left: pos.left
				});

				optionel.show();

				optionel.html('');

				_.each(data.content, function(item) {
					var el=$('
'+item.title+'
').click(function(e) {
						e.stopPropagation();
						e.preventDefault();
						optionel.hide();
						resultel.append(create_autocomplete_item(item, content_type, multiple_status, field_name));
						searchel.val("");
					});
					optionel.append(el);
					indicator.html('Search');
				});
			})
		);
	});

	$(document).on('change', 'input[type=file]', function() {
		var files=this.files; //FileList object
		var el=$(this);
		var container=el.parent();
		var multiple = el.attr("data-multiple");
		var contenttype = el.attr("data-contenttype");
		var name = el.attr("data-name");
		container.find('.progress-container').empty();
		_.each(files, function(f, id) {
			var filename = f.name;
			console.log(f);
			var uid = name + "_" + id;

			$.ajax({
				url: "/api/files/upload?api_key=" + $(document.body).data('api_key') + "&filename="+f.name,  //server script to process data
				type: 'POST',
				xhr: function() {  // custom xhr
					var myXhr = $.ajaxSettings.xhr();
					if (myXhr.upload) { // check if upload property exists
						myXhr.upload.addEventListener('progress', function(data) {
							var percentage = Math.round((data.position / data.total) * 100);
							container.find('.progress-container #' + uid + ' .progress .bar').css('width', percentage + '%');
						}, false); // for handling the progress of the upload
					} // else throw an error here maybe?
					return myXhr;
				},

				//Ajax events
				beforeSend: function(data) {
					container.find('.progress-container').append(_.template($("#field-image-progress").html(), { uid: uid, filename: filename }));
					container.find('.progress-container #' + uid + ' .progress').show();
					container.find('.progress-container #' + uid + '').slideDown();
					container.find('.progress-container .progress .bar').removeClass('bar-success').removeClass('bar-danger');
				},
				success: function(data) {
					var fullname = data.content.full_name;
					var filename = data.content.filename;
					if (data.error) {
						container.find('.progress-container #' + uid + ' .progress').hide().destroy();
						container.find('.progress-container #' + uid + ' .alert').removeClass('alert-success').addClass('alert-error').html('
File upload failed for '+filename+'
 '+data.message).slideDown(500).delay(2000).slideUp(500);
						container.find('.progress-container #' + uid + ' .progress .bar').removeClass('bar-danger').addClass('bar-success');
						return false;
					}
					container.find('.progress-container #' + uid + ' .progress').hide();
					container.find('.progress-container #' + uid + ' .alert').addClass('alert-success').removeClass('alert-error').html('File '+ filename +' uploaded').show().delay(1000).slideDown(500).delay(2000).slideUp(500);

					if (multiple == 1) {
						container.find('.preview-image-items').prepend(_.template($("#field-image-item").html(), { value: fullname, field: { value: fullname, name: name, contenttype: contenttype, multiple: multiple } } ));
					} else {
						container.find('.preview-image-items').html(_.template($("#field-image-item").html(), { value: fullname, field: { value: fullname, name: name, contenttype: contenttype, multiple: multiple } } ));
					}
					el.val(""); //Clear the file upload so we don't upload on form submission
				},
				error: function(xhr, s) {
					container.find('.progress-container #' + uid + ' .alert').removeClass('alert-success').addClass('alert-error').html('File upload failed: '+s).slideDown(500).delay(2000).slideUp(500);
					container.find('.progress-container #' + uid + ' .progress .bar').removeClass('bar-success').addClass('bar-danger');
				},
				// Form data
				data: f,
				//Options to tell JQuery not to process data or worry about content-type
				cache: false,
				contentType: false,
				processData: false,
				timeout: 600000 //10 mins
			});
		});
	});

});

function get_wordcount(sender) {
	sender.nextAll(".wordcount_container").first().find(".wordcount_result").load("/workers/ajax_edit/wordcount", {"str": sender.val()});
}

function init_form() {
	$(".chzn-select").chosen();

	$(".my-datepicker").datepicker({ autoclose: true });

	var autocomplete_timer = false;

	$(".autocomplete").each(function(){
		var self = $(this);
		var self_val = '';
		var origel = this;
		self.keyup(function(){
			if ($.trim(self_val) != $.trim(self.val())) {
				self_val = self.val();
				clearTimeout(autocomplete_timer);
				autocomplete_timer = setTimeout(function(){
				var searchel=self.prev();
				var multiple_status = self.attr('multiple');
				var field_name = self.attr('fieldname');
				var search=self.prev().val();
				var optionel=self.parent().siblings('.options');
				var resultel=self.parent().siblings('.result_container');
				var search_content_type = self.attr("contenttypes");
				var url="/api/content/listing/";
				var search = self.val();
				var indicator = self.parent().siblings('.indicator');
				while(xhr_reqs.length>0) {
					jqXHR=xhr_reqs.pop();
					jqXHR.abort();
				}
				indicator.show();
				xhr_reqs.push(
					$.getJSON("/api/content", { search: search, content_type: search_content_type, limit: 20, fields: ["_id", "title"], order_by: "last_modified" }, function(data) {
						var pos = $.extend({}, searchel.offset(), {
							height: origel.offsetHeight
						});

						optionel.css({
							top: pos.top + pos.height
							, left: pos.left
						});

						if(data.content.length > 0){
							optionel.show();
						}else{
							optionel.hide();
							indicator.hide();
						}
						optionel.html('');
						_.each(data.content, function(item) {
							var el=$('
'+item.title+'
').click(function(e) {
								e.stopPropagation();
								e.preventDefault();
								optionel.hide();
								resultel.append(create_autocomplete_item(item, content_type, multiple_status, field_name));
								searchel.val("");
							});
							optionel.append(el);
							indicator.hide();
						});
					})
				)}, 500);
			}
		});
	});

	$(".countchars").each(function() {
		if ($(this).hasClass("countdown")) {
			var max=$(this).attr("max");
			var current=max-$(this).val().length;
			if (current>=0) {
				$(this).after("
"+current+" chars remaining
");
			} else {
				$(this).after("
"+Math.abs(current)+" chars over
");
			}

			$(this).keyup(function() {
				var max=$(this).attr("max");
				var current=max-$(this).val().length;
				if (current>=0) {
					$(this).next().html(current+" chars remaining").removeClass("red");
				} else {
					$(this).next().html(Math.abs(current)+" chars over").addClass("red");
				}
			});
		} else {
			var current=$(this).val().length;
			$(this).after("
"+current+" chars
");
			$(this).keyup(function() {
				current=$(this).val().length;
				$(this).next().html(current+" chars");
			});
		}
		$(this).removeClass("countchars");
	});

	if ($(".wysiwyg").length) {
		//init_tinymce();
		//clearCKEditor();
		initCKEditor();
	}

	var content_type=$(document.body).data('content_type');
	var urlid=$(document.body).data('urlid');
}<commit_msg>Fix problem where images wouldn't return an error<commit_after>
var xhr_reqs = [];

function create_autocomplete_item(item, content_type, multiple_status, field_name){
	var field = { multiple:multiple_status, contenttype: content_type, name: field_name, value: item._id };
	var newel = _.template($('#field-autocomplete-item').html(), { title:item.title, field: field, item:item});
	return newel;
}

function update_content(data) {
	var results_data=_.template($('#'+data.template).html(), data);
	$('#'+data.element).html(results_data);
}

$(function() {
	$(".result_container div a.close").live('click', function(){
		$(this).parent().remove();
	});

	$('
Word count:

').insertAfter(".wordcount");

	$(".wordcount").keyup(function() {
		get_wordcount($(this));
	});

	$(".wordcount").each(function() {
		get_wordcount($(this));
	});

	$(".remover").live("click", function() { //Not sure if this is still used?
		$(this).parent().remove();
		return false;
	});

	$(document).on('keydown', '.datetime_hour', function(e) {
		var key = e.keyCode;
		if ((key > 33) && (key < 47)) {
			return false;
		}
		if ((key > 58) && (key < 126)) {
			return false;
		}
	});

	$(document).on('blur', '.datetime_hour', function() {
		var v = 0;
		if (($(this).val())) {
			v = Number($(this).val());
			$(this).val(leadingZeros(v));
			if ($(this).val().length > 2) {
				var s = $(this).val();
				$(this).val(s.substring(s.length - 2, s.length));
				v = parseInt($(this).val());
			}
			if (v > 23) {
				$(this).val("23");
			}
		} else {
			$(this).val("00");
		}
		if (!isFinite($(this).val())) {
			$(this).val("00");
		}
	});

	$(document).on('blur', '.datetime_minute', function() {
		if ($(this).val()) {
			var v = Number($(this).val());
			$(this).val(leadingZeros(v));
			if ($(this).val().length > 2) {
				var s = $(this).val();
				$(this).val(s.substring(s.length - 2, s.length));
				v = parseInt($(this).val());
			}
			if (v > 59) {
				$(this).val("59");
			}
		} else {
			$(this).val("00");
		}
		if (!isFinite($(this).val())) {
			$(this).val("00");
		}
	});

	$(document).on('keydown', '.datetime_minute', function(e) {
		var key = e.keyCode;
		if ((key > 33) && (key < 47)) {
			return false;
		}
		if ((key > 58) && (key < 126)) {
			return false;
		}
	});

	$(document).on('keyup', '.datetime_change', function() {
		updateDateTime(this);
	});

	$(document).on('change', '.datetime_change', function() {
		updateDateTime(this);
	});

	function updateDateTime(sender) {
		var parent = $(sender).parent();
		var val = "";
		val += parent.children('.datetime_date').val();
		val += " ";
		val += (parent.children('.datetime_hour').val()) ? parent.children('.datetime_hour').val() : "00";
		val += ":";
		val += (parent.children('.datetime_minute').val()) ? parent.children('.datetime_minute').val() : "00";
		$(sender).siblings(':hidden').val(stringToDate(val));
	}

	$(document).on('click', '.deepsearch-search', function() {
		var multiple_status = $(this).prev().attr('multiple');
		var field_name = $(this).prev().attr('fieldname');
		var searchel=$(this).prev();
		var origel = this;
		var search=$(this).prev().val();
		var content_type=$(this).prev().attr("contenttype");
		var optionel=$(this).parent().siblings('.deepsearch-options');
		var resultel=$(this).parent().siblings('.deepsearch-results');
		var indicator = $(this);
		while(xhr_reqs.length>0) {
			jqXHR=xhr_reqs.pop();
			jqXHR.abort();
		}
		indicator.html("Searching...");
		xhr_reqs.push(
			$.getJSON("/api/content", { search: search, content_type: content_type, limit: 20, fields: ["_id", "title"], order_by: "last_modified" }, function(data) {
				var pos = $.extend({}, searchel.offset(), {
		    		height: origel.offsetHeight
				});

				optionel.css({
					top: pos.top + pos.height
					, left: pos.left
				});

				optionel.show();

				optionel.html('');

				_.each(data.content, function(item) {
					var el=$('
'+item.title+'
').click(function(e) {
						e.stopPropagation();
						e.preventDefault();
						optionel.hide();
						resultel.append(create_autocomplete_item(item, content_type, multiple_status, field_name));
						searchel.val("");
					});
					optionel.append(el);
					indicator.html('Search');
				});
			})
		);
	});

	$(document).on('change', 'input[type=file]', function() {
		var files=this.files; //FileList object
		var el=$(this);
		var container=el.parent();
		var multiple = el.attr("data-multiple");
		var contenttype = el.attr("data-contenttype");
		var name = el.attr("data-name");
		container.find('.progress-container').empty();
		_.each(files, function(f, id) {
			var filename = f.name;
			console.log(f);
			var uid = name + "_" + id;

			$.ajax({
				url: "/api/files/upload?api_key=" + $(document.body).data('api_key') + "&filename="+f.name,  //server script to process data
				type: 'POST',
				xhr: function() {  // custom xhr
					var myXhr = $.ajaxSettings.xhr();
					if (myXhr.upload) { // check if upload property exists
						myXhr.upload.addEventListener('progress', function(data) {
							var percentage = Math.round((data.position / data.total) * 100);
							container.find('.progress-container #' + uid + ' .progress .bar').css('width', percentage + '%');
						}, false); // for handling the progress of the upload
					} // else throw an error here maybe?
					return myXhr;
				},

				//Ajax events
				beforeSend: function(data) {
					container.find('.progress-container').append(_.template($("#field-image-progress").html(), { uid: uid, filename: filename }));
					container.find('.progress-container #' + uid + ' .progress').show();
					container.find('.progress-container #' + uid + '').slideDown();
					container.find('.progress-container .progress .bar').removeClass('bar-success').removeClass('bar-danger');
				},
				success: function(data) {

					if (data.error) {
						container.find('.progress-container #' + uid + ' .progress').hide().destroy();
						container.find('.progress-container #' + uid + ' .alert').removeClass('alert-success').addClass('alert-error').html('
File upload failed for '+filename+'
 '+data.message).slideDown(500).delay(2000).slideUp(500);
						container.find('.progress-container #' + uid + ' .progress .bar').removeClass('bar-danger').addClass('bar-success');
						return false;
					}
					var fullname = data.content.full_name;
					var filename = data.content.filename;
					container.find('.progress-container #' + uid + ' .progress').hide();
					container.find('.progress-container #' + uid + ' .alert').addClass('alert-success').removeClass('alert-error').html('File '+ filename +' uploaded').show().delay(1000).slideDown(500).delay(2000).slideUp(500);

					if (multiple == 1) {
						container.find('.preview-image-items').prepend(_.template($("#field-image-item").html(), { value: fullname, field: { value: fullname, name: name, contenttype: contenttype, multiple: multiple } } ));
					} else {
						container.find('.preview-image-items').html(_.template($("#field-image-item").html(), { value: fullname, field: { value: fullname, name: name, contenttype: contenttype, multiple: multiple } } ));
					}
					el.val(""); //Clear the file upload so we don't upload on form submission
				},
				error: function(xhr, s) {
					container.find('.progress-container #' + uid + ' .alert').removeClass('alert-success').addClass('alert-error').html('File upload failed: '+s).slideDown(500).delay(2000).slideUp(500);
					container.find('.progress-container #' + uid + ' .progress .bar').removeClass('bar-success').addClass('bar-danger');
				},
				// Form data
				data: f,
				//Options to tell JQuery not to process data or worry about content-type
				cache: false,
				contentType: false,
				processData: false,
				timeout: 600000 //10 mins
			});
		});
	});

});

function get_wordcount(sender) {
	sender.nextAll(".wordcount_container").first().find(".wordcount_result").load("/workers/ajax_edit/wordcount", {"str": sender.val()});
}

function init_form() {
	$(".chzn-select").chosen();

	$(".my-datepicker").datepicker({ autoclose: true });

	var autocomplete_timer = false;

	$(".autocomplete").each(function(){
		var self = $(this);
		var self_val = '';
		var origel = this;
		self.keyup(function(){
			if ($.trim(self_val) != $.trim(self.val())) {
				self_val = self.val();
				clearTimeout(autocomplete_timer);
				autocomplete_timer = setTimeout(function(){
				var searchel=self.prev();
				var multiple_status = self.attr('multiple');
				var field_name = self.attr('fieldname');
				var search=self.prev().val();
				var optionel=self.parent().siblings('.options');
				var resultel=self.parent().siblings('.result_container');
				var search_content_type = self.attr("contenttypes");
				var url="/api/content/listing/";
				var search = self.val();
				var indicator = self.parent().siblings('.indicator');
				while(xhr_reqs.length>0) {
					jqXHR=xhr_reqs.pop();
					jqXHR.abort();
				}
				indicator.show();
				xhr_reqs.push(
					$.getJSON("/api/content", { search: search, content_type: search_content_type, limit: 20, fields: ["_id", "title"], order_by: "last_modified" }, function(data) {
						var pos = $.extend({}, searchel.offset(), {
							height: origel.offsetHeight
						});

						optionel.css({
							top: pos.top + pos.height
							, left: pos.left
						});

						if(data.content.length > 0){
							optionel.show();
						}else{
							optionel.hide();
							indicator.hide();
						}
						optionel.html('');
						_.each(data.content, function(item) {
							var el=$('
'+item.title+'
').click(function(e) {
								e.stopPropagation();
								e.preventDefault();
								optionel.hide();
								resultel.append(create_autocomplete_item(item, content_type, multiple_status, field_name));
								searchel.val("");
							});
							optionel.append(el);
							indicator.hide();
						});
					})
				)}, 500);
			}
		});
	});

	$(".countchars").each(function() {
		if ($(this).hasClass("countdown")) {
			var max=$(this).attr("max");
			var current=max-$(this).val().length;
			if (current>=0) {
				$(this).after("
"+current+" chars remaining
");
			} else {
				$(this).after("
"+Math.abs(current)+" chars over
");
			}

			$(this).keyup(function() {
				var max=$(this).attr("max");
				var current=max-$(this).val().length;
				if (current>=0) {
					$(this).next().html(current+" chars remaining").removeClass("red");
				} else {
					$(this).next().html(Math.abs(current)+" chars over").addClass("red");
				}
			});
		} else {
			var current=$(this).val().length;
			$(this).after("
"+current+" chars
");
			$(this).keyup(function() {
				current=$(this).val().length;
				$(this).next().html(current+" chars");
			});
		}
		$(this).removeClass("countchars");
	});

	if ($(".wysiwyg").length) {
		//init_tinymce();
		//clearCKEditor();
		initCKEditor();
	}

	var content_type=$(document.body).data('content_type');
	var urlid=$(document.body).data('urlid');
}<|endoftext|>


<commit_before>/*

MIT License

Copyright (c) 2017 keatec

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.

*/

(function (exports) {

    var buildFunction = function (elem, name, rootfnc, rootname) {
        var html = elem.html;
        var code = [];
        var reg = /\{[^\}]+\}/gi;
        var lines = html.split(reg); expr = html.match(reg) || [];
        var pos = 0; var vname; var vars = {};
        var i;
        for (i = 0; i < lines.length; i++) {
            code.push('' + JSON.stringify(lines[i]));
            if (pos < expr.length) {
                var match = (/\{([\!]{0,1})([a-z]+)(?:\:([^\}]+)){0,1}\}/gi).exec(expr[pos]);
                vname = match[2];
                vars[vname] = match[1] == '!';
                if (match[3] !== undefined) {
                    elem.def[vname] = match[3];
                }
                code.push('(\'\'+' + vname + ' )');
                pos++;
            }
        }
        code = code.join('+\n');
        var fnc;
        var check = []; var checknames = []; var varnames = []; varcheck = {};
        for (i in vars) {
            if (vars[i]) {
                varnames.push('!' + i);
                varcheck[i] = 1;
                check.push('(_opt.' + i + ' === undefined)');
                checknames.push(i);
            } else {
                varnames.push(i);
                varcheck[i] = 1;
            }
        }
        if (check.length > 0) check = ['if (' + check.join(' || ') + ') {throw new Error(\'Generator ' + rootname + '.' + name + ' requires: (' + checknames.join(',') + ') \');};'];
        var fncc = [];
        fncc.push('fnc = function ' + name + ' (_aOpt,_aDef) { ');
        fncc.push('var _def = (_aDef == undefined ? ' + JSON.stringify(elem.def) + ' : _aDef); var _opt = (_aOpt == undefined ? {} : _aOpt);');

        //fncc.push('console.log(_aDef,_aOpt,_opt.title == undefined);');
        fncc.push('var _ars = ' + JSON.stringify(varcheck) + ';');
        fncc.push('for (var _i in _opt) {if (_ars[_i] != 1) {throw new Error(\'Generator ' + rootname + '.' + name + ' does not define a value "\'+_i+\'"\')};};');

        fncc.push(check.join(''));
        for (i in vars) {
            fncc.push('var ' + i + ';');
        }
        for (i in vars) {
            fncc.push('' + i + '= (_opt.' + i + ' != undefined ? _opt.' + i + ': (_def.' + i + ' != undefined ? _def.' + i + ' : \'\'));');
            fncc.push('if (' + i + ' instanceof Array) ' + i + '=' + i + '.join(\'\');');
        }
        fncc.push('; return ' + code + '}');
        //console.log(fncc.join('\r\n'));
        eval('' + fncc.join(''));
        console.log('Generator created: generators' + rootname + '.' + name + '({' + varnames.join(',') + '})');
        rootfnc[name] = fnc;
        elem.fnc = fnc;
        fnc.asActive = function (aObj,aDef) {
            var obj = $(this(aObj,aDef));
            /*obj.data('generator',rootname+'.'+name);data-contextRes
            obj.attr('data-generator',rootname+'.'+name);*/
            obj.data('contextres',JSON.stringify(aObj))
            obj.attr('data-contextres',JSON.stringify(aObj));
            if (obj.hasClass('context')) {
                // ok, this is a Clicker Object;
                var app = obj.data('app');
                if (window[app] != undefined) {
                    if (window[app]['update_'+name] != undefined) {
                        var res = window[app]['update_'+name](obj,aObj);
                        if (res != undefined) {
                            obj.data('contextres',JSON.stringify(res))
                            obj.attr('data-contextres',JSON.stringify(res));
                        }
                    }
                }
            };
            return obj;
        };
        for (i in elem.sub) {
            buildFunction(elem.sub[i], i, fnc, rootname + '.' + name);
        }
    };

    var scanGenerator = function (obj, root) {
        if (obj.data('generator') !== undefined) {
            // There is an Generator
            var name = obj.data('generator');
            if (name.length > 0) {
                obj.removeData('generator');
                obj.removeAttr('data-generator');
                if (root[name] !== undefined) throw new Error('Only one generator definition is allowed per child');
                root.sub[name] = { html: '', sub: {}, def: {} };
                var val = root.sub[name];
                var html = $('<div/>').append(obj.clone());
                var list = html.find('*[data-generatorplace]');
                list.map(function (e) {
                    $(list[e]).replaceWith($('<!--repl:' + $(list[e]).data('generatorplace') + '-->'));
                });
                html.find('*[data-generator]').remove();
                html.find('.htmlGeneratorsDemo').remove();
                html = html.html();
                html = html.replace(/<\!\-\-repl\:([!a-z]+)\-\-\>/gi, function (e, o) {
                    return '{' + o + '}';
                });
                val.html = html;
                obj.children().map(function (e, obj) {
                    scanGenerator($(obj), val);
                });
            }
        } else {
            obj.children().map(function (e, obj) {
                scanGenerator($(obj), root);
            });
        }

    };

    var main = {
        init: function () {
            var data = $('.htmlGenerators');
            if (data.length === 0) return;
            var start = { sub: {} };
            data.map(function (e, obj) {
                scanGenerator($(obj), start);
            });
            for (var i in start.sub) {
                buildFunction(start.sub[i], i, main, '');
            }
        }
    };

    exports.generators = main;

})(window);

$(document).ready(function () {
    generators.init();
});

<commit_msg>patch some lint suggestions<commit_after>/*

MIT License

Copyright (c) 2017 keatec

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.

*/

(function (exports) {

    var buildFunction = function (elem, name, rootfnc, rootname) {
        var html = elem.html;
        var code = [];
        var reg = /\{[^\}]+\}/gi;
        var lines = html.split(reg); expr = html.match(reg) || [];
        var pos = 0; var vname; var vars = {};
        var i;
        for (i = 0; i < lines.length; i++) {
            code.push('' + JSON.stringify(lines[i]));
            if (pos < expr.length) {
                var match = (/\{([\!]{0,1})([a-z]+)(?:\:([^\}]+)){0,1}\}/gi).exec(expr[pos]);
                vname = match[2];
                vars[vname] = match[1] == '!';
                if (match[3] !== undefined) {
                    elem.def[vname] = match[3];
                }
                code.push('(\'\'+' + vname + ' )');
                pos++;
            }
        }
        code = code.join('+\n');
        var fnc;
        var check = []; var checknames = []; var varnames = []; varcheck = {};
        for (i in vars) {
            if (vars[i]) {
                varnames.push('!' + i);
                varcheck[i] = 1;
                check.push('(_opt.' + i + ' === undefined)');
                checknames.push(i);
            } else {
                varnames.push(i);
                varcheck[i] = 1;
            }
        }
        if (check.length > 0) check = ['if (' + check.join(' || ') + ') {throw new Error(\'Generator ' + rootname + '.' + name + ' requires: (' + checknames.join(',') + ') \');};'];
        var fncc = [];
        fncc.push('fnc = function ' + name + ' (_aOpt,_aDef) { ');
        fncc.push('var _def = (_aDef == undefined ? ' + JSON.stringify(elem.def) + ' : _aDef); var _opt = (_aOpt == undefined ? {} : _aOpt);');

        //fncc.push('console.log(_aDef,_aOpt,_opt.title == undefined);');
        fncc.push('var _ars = ' + JSON.stringify(varcheck) + ';');
        fncc.push('for (var _i in _opt) {if (_ars[_i] != 1) {throw new Error(\'Generator ' + rootname + '.' + name + ' does not define a value "\'+_i+\'"\')};};');

        fncc.push(check.join(''));
        for (i in vars) {
            fncc.push('var ' + i + ';');
        }
        for (i in vars) {
            fncc.push('' + i + '= (_opt.' + i + ' != undefined ? _opt.' + i + ': (_def.' + i + ' != undefined ? _def.' + i + ' : \'\'));');
            fncc.push('if (' + i + ' instanceof Array) ' + i + '=' + i + '.join(\'\');');
        }
        fncc.push('; return ' + code + '}');
        //console.log(fncc.join('\r\n'));
        eval('' + fncc.join(''));
        console.log('Generator created: generators' + rootname + '.' + name + '({' + varnames.join(',') + '})');
        rootfnc[name] = fnc;
        elem.fnc = fnc;
        fnc.asActive = function (aObj,aDef) {
            var obj = $(this(aObj,aDef));
            /*obj.data('generator',rootname+'.'+name);data-contextRes
            obj.attr('data-generator',rootname+'.'+name);*/
            obj.data('contextres',JSON.stringify(aObj));
            obj.attr('data-contextres',JSON.stringify(aObj));
            if (obj.hasClass('context')) {
                // ok, this is a Clicker Object;
                var app = obj.data('app');
                if (window[app] !== undefined) {
                    if (window[app]['update_'+name] !== undefined) {
                        var res = window[app]['update_'+name](obj,aObj);
                        if (res !== undefined) {
                            obj.data('contextres',JSON.stringify(res));
                            obj.attr('data-contextres',JSON.stringify(res));
                        }
                    }
                }
            }
            return obj;
        };
        for (i in elem.sub) {
            buildFunction(elem.sub[i], i, fnc, rootname + '.' + name);
        }
    };

    var scanGenerator = function (obj, root) {
        if (obj.data('generator') !== undefined) {
            // There is an Generator
            var name = obj.data('generator');
            if (name.length > 0) {
                obj.removeData('generator');
                obj.removeAttr('data-generator');
                if (root[name] !== undefined) throw new Error('Only one generator definition is allowed per child');
                root.sub[name] = { html: '', sub: {}, def: {} };
                var val = root.sub[name];
                var html = $('<div/>').append(obj.clone());
                var list = html.find('*[data-generatorplace]');
                list.map(function (e) {
                    $(list[e]).replaceWith($('<!--repl:' + $(list[e]).data('generatorplace') + '-->'));
                });
                html.find('*[data-generator]').remove();
                html.find('.htmlGeneratorsDemo').remove();
                html = html.html();
                html = html.replace(/<\!\-\-repl\:([!a-z]+)\-\-\>/gi, function (e, o) {
                    return '{' + o + '}';
                });
                val.html = html;
                obj.children().map(function (e, obj) {
                    scanGenerator($(obj), val);
                });
            }
        } else {
            obj.children().map(function (e, obj) {
                scanGenerator($(obj), root);
            });
        }

    };

    var main = {
        init: function () {
            var data = $('.htmlGenerators');
            if (data.length === 0) return;
            var start = { sub: {} };
            data.map(function (e, obj) {
                scanGenerator($(obj), start);
            });
            for (var i in start.sub) {
                buildFunction(start.sub[i], i, main, '');
            }
        }
    };

    exports.generators = main;

})(window);

$(document).ready(function () {
    generators.init();
});

<|endoftext|>


<commit_before>/**
 * @file DropdownSelect component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Dropdown from '../Dropdown';
import TextField from '../TextField';
import List from '../List';
import DynamicRenderList from '../DynamicRenderList';
import Checkbox from '../Checkbox';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import SelectMode from '../_statics/SelectMode';

class DropdownSelect extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: props.value,
            filter: '',
            popupVisible: false
        };

        this.closePopup = ::this.closePopup;
        this.filterChangeHandler = ::this.filterChangeHandler;
        this.filterData = ::this.filterData;
        this.selectAllTouchTapHandler = ::this.selectAllTouchTapHandler;
        this.itemTouchTapHandler = ::this.itemTouchTapHandler;
        this.changeHandler = ::this.changeHandler;
        this.popupClosedHandler = ::this.popupClosedHandler;
        this.getEmptyEl = ::this.getEmptyEl;
        this.getTriggerValue = ::this.getTriggerValue;

    }

    closePopup() {
        this.refs.dropdown.closePopup();
    }

    filterChangeHandler(filter) {
        this.setState({
            filter
        });
    }

    filterData(filter = this.state.filter, data = this.props.data) {

        if (!filter) {
            return data;
        }

        const {displayField, isGrouped} = this.props,
            filterFunc = (originData) => {
                return originData.filter(item => typeof item === 'object' && !!item[displayField] ?
                    item[displayField].toString().toUpperCase().includes(filter.toUpperCase())
                    :
                    item.toString().toUpperCase().includes(filter.toUpperCase()));
            };

        if (isGrouped) {

            let result = Object.assign(data);

            for (let i = 0, len = result.length; i < len; i++) {
                let group = result[i];
                group.children = filterFunc(group.children);
                if (group.children.length < 1) {
                    result.splice(i, 1);
                    i--;
                }
            }

        }

        return filterFunc(data);

    }

    selectAllTouchTapHandler() {

        const {data} = this.props,
            {value} = this.state;

        if (!data) {
            return;
        }

        const isSelectAll = !value || (value && value.length < data.length),
            newValue = isSelectAll ? data : [];

        this.setState({
            value: newValue
        }, () => {
            this.changeHandler(newValue);
        });

    }

    itemTouchTapHandler(...args) {

        const {autoClose, onItemTouchTap} = this.props;

        if (autoClose) {
            this.closePopup();
        }

        onItemTouchTap && onItemTouchTap(...args);

    }

    changeHandler(value) {

        const {autoClose} = this.props;
        if (autoClose) {
            this.closePopup();
        }

        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });

    }

    popupClosedHandler(e) {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup} = this.props;
            onClosePopup && onClosePopup(e);
        });
    }

    getEmptyEl() {

        const {noMatchedMsg} = this.props;

        return [{
            itemRenderer: () =>

                    {
                        noMatchedMsg ?
                            noMatchedMsg
                            :

                                No matched value.

                    }

        }];

    }

    getTriggerValue() {

        const {placeholder, renderer, valueField, displayField, selectMode} = this.props,
            {value} = this.state,
            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        return value ?
            (
                isMultiSelect ?
                    (
                        value.length > 0 ?
                            value.length + ' selected'
                            :
                            placeholder
                    )
                    :
                    (
                        renderer ?
                            renderer(value)
                            :
                            Util.getTextByDisplayField(value, displayField, valueField)
                    )
            )
            :
            placeholder;

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {

                className, triggerClassName, popupClassName, style, name, popupTheme, data,
                useDynamicRenderList, listHeight, itemHeight, scrollBuffer, renderer,
                selectMode, useFilter, useSelectAll, valueField, displayField, descriptionField, popupChildren,

                // not passing down these props
                noMatchedMsg,

                ...restProps

            } = this.props,
            {value, filter, popupVisible} = this.state,

            isMultiSelect = selectMode === SelectMode.MULTI_SELECT,

            selectClassName = classNames('dropdown-select', {
                [className]: className
            }),
            dropdownTriggerClassName = classNames({
                activated: popupVisible,
                empty: !value,
                [triggerClassName]: triggerClassName
            }),

            triggerValue = this.getTriggerValue(),

            listData = this.filterData();

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <Dropdown {...restProps}
                          ref="dropdown"
                          triggerClassName={dropdownTriggerClassName}
                          popupClassName={'dropdown-select-popup' + (popupClassName ? ' ' + popupClassName : '')}
                          popupTheme={popupTheme}
                          triggerValue={triggerValue}
                          onClosePopup={this.popupClosedHandler}>

                        {
                            useFilter ?
                                <TextField className="dropdown-select-filter"
                                           value={filter}
                                           rightIconCls="fas fa-search"
                                           onChange={this.filterChangeHandler}/>
                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?

                                    <Checkbox className="list-item-select"
                                              checked={data && value && value.length === data.length}
                                              indeterminate={data && value && value.length > 0 && value.length < data.length}/>
                                    Select All

                                :
                                null
                        }

 {
                             Event.wheelHandler(e, this.props);
                         }}>

                        {
                            useFilter ?

                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?

                                :
                                null
                        }

                        {
                            useDynamicRenderList ?
                                <DynamicRenderList className="dropdown-select-list"
                                                   theme={popupTheme}
                                                   selectMode={selectMode}
                                                   data={listData.length < 1 ? this.getEmptyEl() : listData}
                                                   value={value}
                                                   valueField={valueField}
                                                   displayField={displayField}
                                                   descriptionField={descriptionField}
                                                   listHeight={listHeight}
                                                   itemHeight={itemHeight}
                                                   scrollBuffer={scrollBuffer}
                                                   renderer={renderer}
                                                   onItemTouchTap={this.itemTouchTapHandler}
                                                   onChange={this.changeHandler}/>
                                :
                                <List className="dropdown-select-list"
                                      theme={popupTheme}
                                      selectMode={selectMode}
                                      data={listData.length < 1 ? this.getEmptyEl() : listData}
                                      value={value}
                                      valueField={valueField}
                                      displayField={displayField}
                                      descriptionField={descriptionField}
                                      renderer={renderer}
                                      onItemTouchTap={this.itemTouchTapHandler}
                                      onChange={this.changeHandler}/>
                        }

                    {popupChildren}

                </Dropdown>

        );

    }
};

DropdownSelect.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

    /**
     * The placeholder of the dropDownSelect.
     */
    placeholder: PropTypes.string,

    rightIconCls: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            renderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onTouchTap: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

    /**
     * If true,the dropDownSelect will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The select mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    /**
     * If true,the drop-down box will have search input.
     */
    useFilter: PropTypes.bool,

    useSelectAll: PropTypes.bool,

    /**
     * The message of no matching option.
     */
    noMatchedMsg: PropTypes.string,

    shouldPreventContainerScroll: PropTypes.bool,

    popupChildren: PropTypes.any,

    useDynamicRenderList: PropTypes.bool,
    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number,

    renderer: PropTypes.func,

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onItemTouchTap: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func,

    onWheel: PropTypes.func,
    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func

};

DropdownSelect.defaultProps = {

    className: null,
    triggerClassName: null,
    popupClassName: null,
    style: null,
    popupStyle: null,
    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    name: null,
    value: null,
    placeholder: 'Please select ...',
    rightIconCls: 'fas fa-angle-down',
    data: [],
    invalidMsg: null,
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    infoMsg: null,
    autoClose: true,
    useFilter: false,
    useSelectAll: false,
    noMatchedMsg: null,

    shouldPreventContainerScroll: true,

    popupChildren: null,

    useDynamicRenderList: false

};

export default DropdownSelect;<commit_msg>update DropdownSelect<commit_after>/**
 * @file DropdownSelect component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Dropdown from '../Dropdown';
import TextField from '../TextField';
import List from '../List';
import DynamicRenderList from '../DynamicRenderList';
import Checkbox from '../Checkbox';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import SelectMode from '../_statics/SelectMode';

class DropdownSelect extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: props.value,
            filter: ''
        };

        this.closePopup = ::this.closePopup;
        this.filterChangeHandler = ::this.filterChangeHandler;
        this.filterData = ::this.filterData;
        this.selectAllTouchTapHandler = ::this.selectAllTouchTapHandler;
        this.itemTouchTapHandler = ::this.itemTouchTapHandler;
        this.changeHandler = ::this.changeHandler;
        this.popupClosedHandler = ::this.popupClosedHandler;
        this.getEmptyEl = ::this.getEmptyEl;
        this.getTriggerValue = ::this.getTriggerValue;

    }

    closePopup() {
        this.refs.dropdown.closePopup();
    }

    filterChangeHandler(filter) {
        this.setState({
            filter
        });
    }

    filterData(filter = this.state.filter, data = this.props.data) {

        if (!filter) {
            return data;
        }

        const {displayField, isGrouped} = this.props,
            filterFunc = (originData) => {
                return originData.filter(item => typeof item === 'object' && !!item[displayField] ?
                    item[displayField].toString().toUpperCase().includes(filter.toUpperCase())
                    :
                    item.toString().toUpperCase().includes(filter.toUpperCase()));
            };

        if (isGrouped) {

            let result = Object.assign(data);

            for (let i = 0, len = result.length; i < len; i++) {
                let group = result[i];
                group.children = filterFunc(group.children);
                if (group.children.length < 1) {
                    result.splice(i, 1);
                    i--;
                }
            }

        }

        return filterFunc(data);

    }

    selectAllTouchTapHandler() {

        const {data} = this.props,
            {value} = this.state;

        if (!data) {
            return;
        }

        const isSelectAll = !value || (value && value.length < data.length),
            newValue = isSelectAll ? data : [];

        this.setState({
            value: newValue
        }, () => {
            this.changeHandler(newValue);
        });

    }

    itemTouchTapHandler(...args) {

        const {autoClose, onItemTouchTap} = this.props;

        if (autoClose) {
            this.closePopup();
        }

        onItemTouchTap && onItemTouchTap(...args);

    }

    changeHandler(value) {

        const {autoClose} = this.props;
        if (autoClose) {
            this.closePopup();
        }

        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });

    }

    popupClosedHandler(e) {
        const {onClosePopup} = this.props;
        onClosePopup && onClosePopup(e);
    }

    getEmptyEl() {

        const {noMatchedMsg} = this.props;

        return [{
            itemRenderer: () =>

                    {
                        noMatchedMsg ?
                            noMatchedMsg
                            :

                                No matched value.

                    }

        }];

    }

    getTriggerValue() {

        const {placeholder, renderer, valueField, displayField, selectMode} = this.props,
            {value} = this.state,
            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        return value ?
            (
                isMultiSelect ?
                    (
                        value.length > 0 ?
                            value.length + ' selected'
                            :
                            placeholder
                    )
                    :
                    (
                        renderer ?
                            renderer(value)
                            :
                            Util.getTextByDisplayField(value, displayField, valueField)
                    )
            )
            :
            placeholder;

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {

                className, triggerClassName, popupClassName, style, name, popupTheme, data,
                useDynamicRenderList, listHeight, itemHeight, scrollBuffer, renderer,
                selectMode, useFilter, useSelectAll, valueField, displayField, descriptionField, popupChildren,

                // not passing down these props
                noMatchedMsg,

                ...restProps

            } = this.props,
            {value, filter} = this.state,

            isMultiSelect = selectMode === SelectMode.MULTI_SELECT,

            selectClassName = classNames('dropdown-select', {
                [className]: className
            }),
            dropdownTriggerClassName = classNames({
                empty: !value,
                [triggerClassName]: triggerClassName
            }),

            triggerValue = this.getTriggerValue(),

            listData = this.filterData();

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <Dropdown {...restProps}
                          ref="dropdown"
                          triggerClassName={dropdownTriggerClassName}
                          popupClassName={'dropdown-select-popup' + (popupClassName ? ' ' + popupClassName : '')}
                          popupTheme={popupTheme}
                          triggerValue={triggerValue}
                          onClosePopup={this.popupClosedHandler}>

                        {
                            useFilter ?
                                <TextField className="dropdown-select-filter"
                                           value={filter}
                                           rightIconCls="fas fa-search"
                                           onChange={this.filterChangeHandler}/>
                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?

                                    <Checkbox className="list-item-select"
                                              checked={data && value && value.length === data.length}
                                              indeterminate={data && value && value.length > 0 && value.length < data.length}/>
                                    Select All

                                :
                                null
                        }

 {
                             Event.wheelHandler(e, this.props);
                         }}>

                        {
                            useFilter ?

                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?

                                :
                                null
                        }

                        {
                            useDynamicRenderList ?
                                <DynamicRenderList className="dropdown-select-list"
                                                   theme={popupTheme}
                                                   selectMode={selectMode}
                                                   data={listData.length < 1 ? this.getEmptyEl() : listData}
                                                   value={value}
                                                   valueField={valueField}
                                                   displayField={displayField}
                                                   descriptionField={descriptionField}
                                                   listHeight={listHeight}
                                                   itemHeight={itemHeight}
                                                   scrollBuffer={scrollBuffer}
                                                   renderer={renderer}
                                                   onItemTouchTap={this.itemTouchTapHandler}
                                                   onChange={this.changeHandler}/>
                                :
                                <List className="dropdown-select-list"
                                      theme={popupTheme}
                                      selectMode={selectMode}
                                      data={listData.length < 1 ? this.getEmptyEl() : listData}
                                      value={value}
                                      valueField={valueField}
                                      displayField={displayField}
                                      descriptionField={descriptionField}
                                      renderer={renderer}
                                      onItemTouchTap={this.itemTouchTapHandler}
                                      onChange={this.changeHandler}/>
                        }

                    {popupChildren}

                </Dropdown>

        );

    }
};

DropdownSelect.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

    /**
     * The placeholder of the dropDownSelect.
     */
    placeholder: PropTypes.string,

    rightIconCls: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            renderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onTouchTap: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

    /**
     * If true,the dropDownSelect will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The select mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    /**
     * If true,the drop-down box will have search input.
     */
    useFilter: PropTypes.bool,

    useSelectAll: PropTypes.bool,

    /**
     * The message of no matching option.
     */
    noMatchedMsg: PropTypes.string,

    shouldPreventContainerScroll: PropTypes.bool,

    popupChildren: PropTypes.any,

    useDynamicRenderList: PropTypes.bool,
    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number,

    renderer: PropTypes.func,

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onItemTouchTap: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func,

    onWheel: PropTypes.func,
    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func

};

DropdownSelect.defaultProps = {

    className: null,
    triggerClassName: null,
    popupClassName: null,
    style: null,
    popupStyle: null,
    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    name: null,
    value: null,
    placeholder: 'Please select ...',
    rightIconCls: 'fas fa-angle-down',
    data: [],
    invalidMsg: null,
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    infoMsg: null,
    autoClose: true,
    useFilter: false,
    useSelectAll: false,
    noMatchedMsg: null,

    shouldPreventContainerScroll: true,

    popupChildren: null,

    useDynamicRenderList: false

};

export default DropdownSelect;<|endoftext|>


<commit_before>/*

MIT License

Copyright (c) 2017 keatec

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.

*/

(function (exports) {

    var buildFunction = function (elem, name, rootfnc, rootname) {
        var html = elem.html;
        var code = [];
        var reg = /\{[^\}]+\}/gi;
        var lines = html.split(reg); expr = html.match(reg) || [];
        var pos = 0; var vname; var vars = {};
        var i;
        for (i = 0; i < lines.length; i++) {
            code.push('' + JSON.stringify(lines[i]));
            if (pos < expr.length) {
                var match = (/\{([\!]{0,1})([a-z]+)(?:\:([^\}]+)){0,1}\}/gi).exec(expr[pos]);
                vname = match[2];
                vars[vname] = match[1] == '!';
                if (match[3] !== undefined) {
                    elem.def[vname] = match[3];
                }
                code.push('(\'\'+' + vname + ' )');
                pos++;
            }
        }
        code = code.join('+\n');
        var fnc;
        var check = []; var checknames = []; var varnames = []; varcheck = {};
        for (i in vars) {
            if (vars[i]) {
                varnames.push('!' + i);
                varcheck[i] = 1;
                check.push('(_opt.' + i + ' === undefined)');
                checknames.push(i);
            } else {
                varnames.push(i);
                varcheck[i] = 1;
            }
        }
        if (check.length > 0) check = ['if (' + check.join(' || ') + ') {throw new Error(\'Generator ' + rootname + '.' + name + ' requires: (' + checknames.join(',') + ') \');};'];
        var fncc = [];
        fncc.push('fnc = function ' + name + ' (_aOpt,_aDef) { ');
        fncc.push('var _def = (_aDef == undefined ? ' + JSON.stringify(elem.def) + ' : _aDef); var _opt = (_aOpt == undefined ? {} : _aOpt);');

        //fncc.push('console.log(_aDef,_aOpt,_opt.title == undefined);');
        fncc.push('var _ars = ' + JSON.stringify(varcheck) + ';');
        fncc.push('for (var _i in _opt) {if (_ars[_i] != 1) {throw new Error(\'Generator ' + rootname + '.' + name + ' does not define a value "\'+_i+\'"\')};};');

        fncc.push(check.join(''));
        for (i in vars) {
            fncc.push('var ' + i + ';');
        }
        for (i in vars) {
            fncc.push('' + i + '= (_opt.' + i + ' != undefined ? _opt.' + i + ': (_def.' + i + ' != undefined ? _def.' + i + ' : \'\'));');
            fncc.push('if (' + i + ' instanceof Array) ' + i + '=' + i + '.join(\'\');');
        }
        fncc.push('; return ' + code + '}');
        //console.log(fncc.join('\r\n'));
        eval('' + fncc.join(''));
        console.log('Generator created: generators' + rootname + '.' + name + '({' + varnames.join(',') + '})');
        rootfnc[name] = fnc;
        elem.fnc = fnc;
        fnc.asActive = function (aObj,aDef) {
            var obj = $(this(aObj,aDef));
            /*obj.data('generator',rootname+'.'+name);data-contextRes
            obj.attr('data-generator',rootname+'.'+name);*/
            obj.data('contextres',JSON.stringify(aObj))
            obj.attr('data-contextres',JSON.stringify(aObj));
            if (obj.hasClass('context')) {
                // ok, this is a Clicker Object;
                var app = obj.data('app');
                if (window[app] != undefined) {
                    if (window[app]['created_'+name] != undefined) {
                        var res = window[app]['created_'+name](obj,aObj);
                        if (res != undefined) {
                            obj.data('contextres',JSON.stringify(res))
                            obj.attr('data-contextres',JSON.stringify(res));
                        }
                    }
                }
            };
            return obj;
        };
        for (i in elem.sub) {
            buildFunction(elem.sub[i], i, fnc, rootname + '.' + name);
        }
    };

    var scanGenerator = function (obj, root) {
        if (obj.data('generator') !== undefined) {
            // There is an Generator
            var name = obj.data('generator');
            if (name.length > 0) {
                obj.removeData('generator');
                obj.removeAttr('data-generator');
                if (root[name] !== undefined) throw new Error('Only one generator definition is allowed per child');
                root.sub[name] = { html: '', sub: {}, def: {} };
                var val = root.sub[name];
                var html = $('<div/>').append(obj.clone());
                var list = html.find('*[data-generatorplace]');
                list.map(function (e) {
                    $(list[e]).replaceWith($('<!--repl:' + $(list[e]).data('generatorplace') + '-->'));
                });
                html.find('*[data-generator]').remove();
                html.find('.htmlGeneratorsDemo').remove();
                html = html.html();
                html = html.replace(/<\!\-\-repl\:([!a-z]+)\-\-\>/gi, function (e, o) {
                    return '{' + o + '}';
                });
                val.html = html;
                obj.children().map(function (e, obj) {
                    scanGenerator($(obj), val);
                });
            }
        } else {
            obj.children().map(function (e, obj) {
                scanGenerator($(obj), root);
            });
        }

    };

    var main = {
        init: function () {
            var data = $('.htmlGenerators');
            if (data.length === 0) return;
            var start = { sub: {} };
            data.map(function (e, obj) {
                scanGenerator($(obj), start);
            });
            for (var i in start.sub) {
                buildFunction(start.sub[i], i, main, '');
            }
        }
    };

    exports.generators = main;

})(window);

$(document).ready(function () {
    generators.init();
});

<commit_msg>patch created to update to match workflow naming better<commit_after>/*

MIT License

Copyright (c) 2017 keatec

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.

*/

(function (exports) {

    var buildFunction = function (elem, name, rootfnc, rootname) {
        var html = elem.html;
        var code = [];
        var reg = /\{[^\}]+\}/gi;
        var lines = html.split(reg); expr = html.match(reg) || [];
        var pos = 0; var vname; var vars = {};
        var i;
        for (i = 0; i < lines.length; i++) {
            code.push('' + JSON.stringify(lines[i]));
            if (pos < expr.length) {
                var match = (/\{([\!]{0,1})([a-z]+)(?:\:([^\}]+)){0,1}\}/gi).exec(expr[pos]);
                vname = match[2];
                vars[vname] = match[1] == '!';
                if (match[3] !== undefined) {
                    elem.def[vname] = match[3];
                }
                code.push('(\'\'+' + vname + ' )');
                pos++;
            }
        }
        code = code.join('+\n');
        var fnc;
        var check = []; var checknames = []; var varnames = []; varcheck = {};
        for (i in vars) {
            if (vars[i]) {
                varnames.push('!' + i);
                varcheck[i] = 1;
                check.push('(_opt.' + i + ' === undefined)');
                checknames.push(i);
            } else {
                varnames.push(i);
                varcheck[i] = 1;
            }
        }
        if (check.length > 0) check = ['if (' + check.join(' || ') + ') {throw new Error(\'Generator ' + rootname + '.' + name + ' requires: (' + checknames.join(',') + ') \');};'];
        var fncc = [];
        fncc.push('fnc = function ' + name + ' (_aOpt,_aDef) { ');
        fncc.push('var _def = (_aDef == undefined ? ' + JSON.stringify(elem.def) + ' : _aDef); var _opt = (_aOpt == undefined ? {} : _aOpt);');

        //fncc.push('console.log(_aDef,_aOpt,_opt.title == undefined);');
        fncc.push('var _ars = ' + JSON.stringify(varcheck) + ';');
        fncc.push('for (var _i in _opt) {if (_ars[_i] != 1) {throw new Error(\'Generator ' + rootname + '.' + name + ' does not define a value "\'+_i+\'"\')};};');

        fncc.push(check.join(''));
        for (i in vars) {
            fncc.push('var ' + i + ';');
        }
        for (i in vars) {
            fncc.push('' + i + '= (_opt.' + i + ' != undefined ? _opt.' + i + ': (_def.' + i + ' != undefined ? _def.' + i + ' : \'\'));');
            fncc.push('if (' + i + ' instanceof Array) ' + i + '=' + i + '.join(\'\');');
        }
        fncc.push('; return ' + code + '}');
        //console.log(fncc.join('\r\n'));
        eval('' + fncc.join(''));
        console.log('Generator created: generators' + rootname + '.' + name + '({' + varnames.join(',') + '})');
        rootfnc[name] = fnc;
        elem.fnc = fnc;
        fnc.asActive = function (aObj,aDef) {
            var obj = $(this(aObj,aDef));
            /*obj.data('generator',rootname+'.'+name);data-contextRes
            obj.attr('data-generator',rootname+'.'+name);*/
            obj.data('contextres',JSON.stringify(aObj))
            obj.attr('data-contextres',JSON.stringify(aObj));
            if (obj.hasClass('context')) {
                // ok, this is a Clicker Object;
                var app = obj.data('app');
                if (window[app] != undefined) {
                    if (window[app]['update_'+name] != undefined) {
                        var res = window[app]['update_'+name](obj,aObj);
                        if (res != undefined) {
                            obj.data('contextres',JSON.stringify(res))
                            obj.attr('data-contextres',JSON.stringify(res));
                        }
                    }
                }
            };
            return obj;
        };
        for (i in elem.sub) {
            buildFunction(elem.sub[i], i, fnc, rootname + '.' + name);
        }
    };

    var scanGenerator = function (obj, root) {
        if (obj.data('generator') !== undefined) {
            // There is an Generator
            var name = obj.data('generator');
            if (name.length > 0) {
                obj.removeData('generator');
                obj.removeAttr('data-generator');
                if (root[name] !== undefined) throw new Error('Only one generator definition is allowed per child');
                root.sub[name] = { html: '', sub: {}, def: {} };
                var val = root.sub[name];
                var html = $('<div/>').append(obj.clone());
                var list = html.find('*[data-generatorplace]');
                list.map(function (e) {
                    $(list[e]).replaceWith($('<!--repl:' + $(list[e]).data('generatorplace') + '-->'));
                });
                html.find('*[data-generator]').remove();
                html.find('.htmlGeneratorsDemo').remove();
                html = html.html();
                html = html.replace(/<\!\-\-repl\:([!a-z]+)\-\-\>/gi, function (e, o) {
                    return '{' + o + '}';
                });
                val.html = html;
                obj.children().map(function (e, obj) {
                    scanGenerator($(obj), val);
                });
            }
        } else {
            obj.children().map(function (e, obj) {
                scanGenerator($(obj), root);
            });
        }

    };

    var main = {
        init: function () {
            var data = $('.htmlGenerators');
            if (data.length === 0) return;
            var start = { sub: {} };
            data.map(function (e, obj) {
                scanGenerator($(obj), start);
            });
            for (var i in start.sub) {
                buildFunction(start.sub[i], i, main, '');
            }
        }
    };

    exports.generators = main;

})(window);

$(document).ready(function () {
    generators.init();
});

<|endoftext|>