<commit_before>boomPage.prototype.saveSettings = function(url, data, success_message) {
	return $.boom.post(url, data)
		.done(function() {
			if (success_message) {
				$.boom.growl.show(success_message);
			}
		});
};

boomPage.prototype.navigation = function() {
	var page = this,
		url = '/cms/page/settings/navigation/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Navigation',
		width: 570,
		onLoad : function() {
			$(this).find('.boom-tree').pageTree({
				onPageSelect : function(page) {
					$( 'input[name=parent_id]' ).val( page.page_rid );
				}
			});
		},
		callback: function() {
			page.saveSettings(url, $(this).find('form').serialize(), 'Page navigation settings saved');
		},
		open: function() {
			var parent_id = $( 'input[name=parent_id]' ).val();
			$( '#page_' + parent_id ).addClass( 'ui-state-active' );
		}
	});
};

boomPage.prototype.search = function() {
	var page = this,
		url = '/cms/page/settings/search/' + page.id;

	$.boom.dialog.open({
		url : url,
		title : 'Search Settings',
		width : 500,
		callback : function() {
			page.saveSettings(url, $(this).find("form").serialize(), 'Page search settings saved');
		}
	});
};

boomPage.prototype.tags = function() {
	var page = this,
		dialog;

	dialog = $.boom.dialog.open({
		url: '/cms/tags/page/list/' + page.id,
		title: 'Page tags',
		width: 440,
		open: function() {
			$('#b-tags').tagger({
				type: 'page',
				id: page.id
			});
		},
		buttons: [
			{
				text: 'Close',
				class : 'b-button',
				icons: { primary : 'b-button-icon b-button-icon-accept' },
				click: function(event) {
					$.boom.dialog.destroy(dialog);
				}
			}
		]
	});
};

boomPage.prototype.urls = function() {
	var urlEditor = new boomUrlEditor(this);
	urlEditor.open();
};

boomPage.prototype.featureimage = function() {
	var	page = this,
		url = '/cms/page/version/feature/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Page feature image',
		width: 300,
		buttons: [
			{
				text: 'Add',
				id: 'boom-feature-add',
				class : 'b-button',
				icons: { primary: 'b-button-icon b-button-icon-add' },
				click: function(){
					$.boom.assets
						.picker({
							asset_rid : $('#boom-featureimage-input').val()
						})
						.done( function( rid ){
							$('#boom-featureimage-img').attr( 'src', '/asset/view/' + rid + '/250/80').show();
							$('#boom-featureimage-input').val( rid );
							$( '#b-feature-remove' ).button( 'enable' );
							$( '#boom-featureimage-none' ).hide();
						});
				}
			},
			{
				text: 'Remove',
				class : 'b-button',
				id: 'b-feature-remove',
				icons: { primary: 'b-button-icon b-button-icon-delete' },
				click: function(){
					var dialog = $(this);
					$.boom.dialog.confirm(
						'Please confirm',
						"Are you sure you want to do delete this page's feature image?"
					)
					.done( function(){

						$('#boom-featureimage-img').attr( 'src', '').hide();
						$('#boom-featureimage-input').val( 0 );
						$( '#b-feature-remove' ).button( 'disable' );
						$( '#boom-featureimage-none' ).show();
					});
				}
			},
			{
				text: 'Cancel',
				class : 'b-button',
				icons: { primary: 'b-button-icon b-button-icon-cancel' },
				click: function(){

					$.boom.dialog.destroy( this );
				}
			},
			{
				text: 'Okay',
				class : 'b-button',
				icons: { primary: 'b-button-icon b-button-icon-accept' },
				click: function() {
					page.saveSettings(url, $("#boom-form-pagesettings-featureimage").serialize(), '"Page feature image saved')
						.done(function(response) {
							page.toolbar.status.set(response);
						});

					$.boom.dialog.destroy(this);
				}
			}
		],
		open: function(){
			$( '#b-feature-remove' ).button( 'disable' );
		},
		onLoad: function(){
			var asset_id = $('#boom-featureimage-input').val();

			if ( asset_id > 0 ) {
				$( '#boom-featureimage-none' ).hide();
				$( '#b-feature-remove' ).button( 'enable' );
			}
		}
	});
};

boomPage.prototype.template = function() {
	var	page = this,
		url = '/cms/page/version/template/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Page template',
		width: 500,
		callback: function() {
			page.saveSettings(url, $("#b-page-version-template").serialize(), 'Page template saved, reloading page')
				.done(function() {
					// Reload the page to show the template change.
					top.location.reload();
				});

		},
		open: function() {
			page.template._show_details();

			$(this).find('select').on('change', function() {
				page.template._show_details();
			});
		}
	});

	boomPage.prototype.template._show_details = function() {
		var $template = $('#template'),
			$description = $('#description'),
			$count = $('#count'),
			$selected = $template.find('option:selected'),
			description_text = $selected.data('description');

		if (description_text) {
			$description.show().find('p').html($selected.data('description'));
		} else {
			$description.hide();
		}
		$count.find('p').html($selected.data('count'));
	};
};

boomPage.prototype.visibility = function() {
	var	page = this,
		url = '/cms/page/settings/visibility/' + page.id,
		deferred = new $.Deferred();

	$.boom.dialog.open({
		url: url,
		title: 'Page visibility',
		width: 440,
		callback: function(){
			page.saveSettings(url, $(this).find("form").serialize(), 'Page visibility settings saved')
				.done(function(response) {
					deferred.resolve(response);
				});
		},
		open: function(){

			$('#toggle-visible:checkbox').unbind('change').change(function(){

				if (this.checked) {

					$('#visible-to, #visible-to-time').removeAttr('disabled');

					if ($('#visible-to').val().toLowerCase().trim() == 'forever') {

						$('#visible-to').val('');
					}

					$('#visible-to').focus();

				} else {

					$('#visible-to, #visible-to-time').attr('disabled', 'disabled');

					if (!$('#visible-to').val().trim().length) {

						$('#visible-to').val('forever');
					}

					$('#visible-to').blur();
				}
			});

			$('#visible').on('change', function() {
				switch( $( this ).val() ) {
					case '1':
						$( '#visible-from' ).removeAttr( 'disabled' );
					break;
					case '0':
						$( '#visible-from' ).attr( 'disabled', 'disabled' );
						$( '#visible-to' ).attr( 'disabled', 'disabled' );
					break;
				}
			});

			if ($('#visible').val() == '0') {
				$( '#visible-from' ).attr( 'disabled', 'disabled' );
				$( '#visible-to' ).attr( 'disabled', 'disabled' );
			}
		}
	});

	return deferred;
};

boomPage.prototype.childsettings = function() {
	var page = this,
		url = '/cms/page/settings/children/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Child page settings',
		width: '510px',
		open: function() {
			$('select[name="children_ordering_policy"]').on('change', function(){
				var reorder_link = $('#b-page-settings-children-reorder');

				if ($(this).val() == 'sequence')
				{
					reorder_link.removeClass('ui-helper-hidden');
				}
				else
				{
					reorder_link.addClass('ui-helper-hidden');
				}
			});

			$('#b-page-settings-children-reorder').on('click', function() {
				var sort_url = '/cms/page/settings/sort_children/' + page.id;
				$.boom.dialog.open({
					url:  sort_url,
					title: 'Reorder child pages',
					width: 'auto',
					open: function() {
						$('#b-page-settings-children-sort').sortable();
					},
					callback: function(){
						var sequences = $('#b-page-settings-children-sort li').map(function(){
							return $(this).attr('data-id');
						}).get();

						page.saveSettings(url, $("form.b-form-settings").serialize())
							.done(function() {
								page.saveSettings(url, {sequences : sequences}, 'Child page ordering saved, reloading page');
							});
					}
				});
			});
		},
		callback: function(){
			page.saveSettings(url, $(this).find("form").serialize(), 'Child page settings saved');
		}
	});
};

boomPage.prototype.adminsettings = function() {
	var page = this,
		url = '/cms/page/settings/admin/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Admin settings',
		width: 'auto',
		callback: function(){
			page.saveSettings(url, $(this).find("form").serialize(), 'Page admin settings saved');
		}
	});
};<commit_msg>Bugfix: child page manual ordering not saving<commit_after>boomPage.prototype.saveSettings = function(url, data, success_message) {
	return $.boom.post(url, data)
		.done(function() {
			if (success_message) {
				$.boom.growl.show(success_message);
			}
		});
};

boomPage.prototype.navigation = function() {
	var page = this,
		url = '/cms/page/settings/navigation/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Navigation',
		width: 570,
		onLoad : function() {
			$(this).find('.boom-tree').pageTree({
				onPageSelect : function(page) {
					$( 'input[name=parent_id]' ).val( page.page_rid );
				}
			});
		},
		callback: function() {
			page.saveSettings(url, $(this).find('form').serialize(), 'Page navigation settings saved');
		},
		open: function() {
			var parent_id = $( 'input[name=parent_id]' ).val();
			$( '#page_' + parent_id ).addClass( 'ui-state-active' );
		}
	});
};

boomPage.prototype.search = function() {
	var page = this,
		url = '/cms/page/settings/search/' + page.id;

	$.boom.dialog.open({
		url : url,
		title : 'Search Settings',
		width : 500,
		callback : function() {
			page.saveSettings(url, $(this).find("form").serialize(), 'Page search settings saved');
		}
	});
};

boomPage.prototype.tags = function() {
	var page = this,
		dialog;

	dialog = $.boom.dialog.open({
		url: '/cms/tags/page/list/' + page.id,
		title: 'Page tags',
		width: 440,
		open: function() {
			$('#b-tags').tagger({
				type: 'page',
				id: page.id
			});
		},
		buttons: [
			{
				text: 'Close',
				class : 'b-button',
				icons: { primary : 'b-button-icon b-button-icon-accept' },
				click: function(event) {
					$.boom.dialog.destroy(dialog);
				}
			}
		]
	});
};

boomPage.prototype.urls = function() {
	var urlEditor = new boomUrlEditor(this);
	urlEditor.open();
};

boomPage.prototype.featureimage = function() {
	var	page = this,
		url = '/cms/page/version/feature/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Page feature image',
		width: 300,
		buttons: [
			{
				text: 'Add',
				id: 'boom-feature-add',
				class : 'b-button',
				icons: { primary: 'b-button-icon b-button-icon-add' },
				click: function(){
					$.boom.assets
						.picker({
							asset_rid : $('#boom-featureimage-input').val()
						})
						.done( function( rid ){
							$('#boom-featureimage-img').attr( 'src', '/asset/view/' + rid + '/250/80').show();
							$('#boom-featureimage-input').val( rid );
							$( '#b-feature-remove' ).button( 'enable' );
							$( '#boom-featureimage-none' ).hide();
						});
				}
			},
			{
				text: 'Remove',
				class : 'b-button',
				id: 'b-feature-remove',
				icons: { primary: 'b-button-icon b-button-icon-delete' },
				click: function(){
					var dialog = $(this);
					$.boom.dialog.confirm(
						'Please confirm',
						"Are you sure you want to do delete this page's feature image?"
					)
					.done( function(){

						$('#boom-featureimage-img').attr( 'src', '').hide();
						$('#boom-featureimage-input').val( 0 );
						$( '#b-feature-remove' ).button( 'disable' );
						$( '#boom-featureimage-none' ).show();
					});
				}
			},
			{
				text: 'Cancel',
				class : 'b-button',
				icons: { primary: 'b-button-icon b-button-icon-cancel' },
				click: function(){

					$.boom.dialog.destroy( this );
				}
			},
			{
				text: 'Okay',
				class : 'b-button',
				icons: { primary: 'b-button-icon b-button-icon-accept' },
				click: function() {
					page.saveSettings(url, $("#boom-form-pagesettings-featureimage").serialize(), '"Page feature image saved')
						.done(function(response) {
							page.toolbar.status.set(response);
						});

					$.boom.dialog.destroy(this);
				}
			}
		],
		open: function(){
			$( '#b-feature-remove' ).button( 'disable' );
		},
		onLoad: function(){
			var asset_id = $('#boom-featureimage-input').val();

			if ( asset_id > 0 ) {
				$( '#boom-featureimage-none' ).hide();
				$( '#b-feature-remove' ).button( 'enable' );
			}
		}
	});
};

boomPage.prototype.template = function() {
	var	page = this,
		url = '/cms/page/version/template/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Page template',
		width: 500,
		callback: function() {
			page.saveSettings(url, $("#b-page-version-template").serialize(), 'Page template saved, reloading page')
				.done(function() {
					// Reload the page to show the template change.
					top.location.reload();
				});

		},
		open: function() {
			page.template._show_details();

			$(this).find('select').on('change', function() {
				page.template._show_details();
			});
		}
	});

	boomPage.prototype.template._show_details = function() {
		var $template = $('#template'),
			$description = $('#description'),
			$count = $('#count'),
			$selected = $template.find('option:selected'),
			description_text = $selected.data('description');

		if (description_text) {
			$description.show().find('p').html($selected.data('description'));
		} else {
			$description.hide();
		}
		$count.find('p').html($selected.data('count'));
	};
};

boomPage.prototype.visibility = function() {
	var	page = this,
		url = '/cms/page/settings/visibility/' + page.id,
		deferred = new $.Deferred();

	$.boom.dialog.open({
		url: url,
		title: 'Page visibility',
		width: 440,
		callback: function(){
			page.saveSettings(url, $(this).find("form").serialize(), 'Page visibility settings saved')
				.done(function(response) {
					deferred.resolve(response);
				});
		},
		open: function(){

			$('#toggle-visible:checkbox').unbind('change').change(function(){

				if (this.checked) {

					$('#visible-to, #visible-to-time').removeAttr('disabled');

					if ($('#visible-to').val().toLowerCase().trim() == 'forever') {

						$('#visible-to').val('');
					}

					$('#visible-to').focus();

				} else {

					$('#visible-to, #visible-to-time').attr('disabled', 'disabled');

					if (!$('#visible-to').val().trim().length) {

						$('#visible-to').val('forever');
					}

					$('#visible-to').blur();
				}
			});

			$('#visible').on('change', function() {
				switch( $( this ).val() ) {
					case '1':
						$( '#visible-from' ).removeAttr( 'disabled' );
					break;
					case '0':
						$( '#visible-from' ).attr( 'disabled', 'disabled' );
						$( '#visible-to' ).attr( 'disabled', 'disabled' );
					break;
				}
			});

			if ($('#visible').val() == '0') {
				$( '#visible-from' ).attr( 'disabled', 'disabled' );
				$( '#visible-to' ).attr( 'disabled', 'disabled' );
			}
		}
	});

	return deferred;
};

boomPage.prototype.childsettings = function() {
	var page = this,
		url = '/cms/page/settings/children/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Child page settings',
		width: '510px',
		open: function() {
			$('select[name="children_ordering_policy"]').on('change', function(){
				var reorder_link = $('#b-page-settings-children-reorder');

				if ($(this).val() == 'sequence')
				{
					reorder_link.removeClass('ui-helper-hidden');
				}
				else
				{
					reorder_link.addClass('ui-helper-hidden');
				}
			});

			$('#b-page-settings-children-reorder').on('click', function() {
				var sort_url = '/cms/page/settings/sort_children/' + page.id;
				$.boom.dialog.open({
					url:  sort_url,
					title: 'Reorder child pages',
					width: 'auto',
					open: function() {
						$('#b-page-settings-children-sort').sortable();
					},
					callback: function(){
						var sequences = $('#b-page-settings-children-sort li').map(function(){
							return $(this).attr('data-id');
						}).get();

						page.saveSettings(url, $("form.b-form-settings").serialize())
							.done(function() {
								page.saveSettings('/cms/page/settings/sort_children/' + page.id, {sequences : sequences}, 'Child page ordering saved');
							});
					}
				});
			});
		},
		callback: function(){
			page.saveSettings(url, $(this).find("form").serialize(), 'Child page settings saved');
		}
	});
};

boomPage.prototype.adminsettings = function() {
	var page = this,
		url = '/cms/page/settings/admin/' + page.id;

	$.boom.dialog.open({
		url: url,
		title: 'Admin settings',
		width: 'auto',
		callback: function(){
			page.saveSettings(url, $(this).find("form").serialize(), 'Page admin settings saved');
		}
	});
};<|endoftext|>


<commit_before>/** -*- compile-command: "jslint-cli ShaderParameterVisitor.js" -*-
 * Authors:
 *  Cedric Pinson <cedric.pinson@plopbyte.com>
 */

(function() {

    var ArraySlider = function(params) {
        if (params !== undefined) {
            if (params.object !== undefined && params.field !== undefined) {
                this.createInternalSlider(param);
            }
            this._uniform = this.createInternalSliderUniform(param);
        }
    };

    ArraySlider.prototype = {
        setTargetHTML: function(target) {
            this.parent = target;
        },
        addToDom: function(content) {
            var mydiv = document.createElement('div');
            mydiv.innerHTML = content;
            this.parent.appendChild(mydiv);
        },

        getValue: function(name) {
            if (window.localStorage) {
                var value = window.localStorage.getItem(name);
                return value;
            }
            return null;
        },
        setValue: function(name, value) {
            if (window.localStorage) {
                window.localStorage.setItem(name, value);
            }
        },
        createHTMLSlider: function(param, value, nameIndex, cbnameIndex) {
            var input = '
NAME [ MIN - MAX ] <input type="range" min="MIN" max="MAX" value="VALUE" step="STEP" onchange="ONCHANGE" />
';
            var min = param.min;
            var max = param.max;
            var step = param.step;
            var name = nameIndex;
            var cbname = cbnameIndex;
            var onchange = cbname + '(this.value)';
            input = input.replace(/MIN/g, min);
            input = input.replace(/MAX/g, (max+step));
            input = input.replace('STEP', step);
            input = input.replace('VALUE', value);
            input = input.replace(/NAME/g, name);
            input = input.replace(/UPDATE/g, cbname);
            input = input.replace('ONCHANGE', onchange);
            return input;
        },

        createUniformFunction: function(param, name, index, uniform, cbnameIndex) {
            self = this;
            return (function() {
                var cname = name;
                var cindex = index;
                var cuniform = uniform;
                var id = cbnameIndex;
                var func = function(value) {
                    cuniform.get()[cindex] = value;
                    cuniform.dirty();
                    osg.debug(cname + ' value ' + value);
                    document.getElementById(cbnameIndex).innerHTML = Number(value).toFixed(4);
                    self.setValue(id, value);
                    if (param.onchange !== undefined) {
                        param.onchange(cuniform.get());
                    }
                    // store the value to localstorage
                };
                return func;
            })();
        },

        createFunction: function(param, name, index, object, field, cbnameIndex) {
            self = this;
            return (function() {
                var cname = name;
                var cindex = index;
                var cfield = field;
                var id = cbnameIndex;
                var obj = object;
                var func = function(value) {
                    if (typeof(value) === 'string') {
                        value = parseFloat(value);
                    }

                    if (typeof(object[cfield]) === 'number') {
                        obj[cfield] = value;
                    } else {
                        obj[cfield][index] = value;
                    }
                    osg.debug(cname + ' value ' + value);
                    document.getElementById(cbnameIndex).innerHTML = Number(value).toFixed(4);
                    self.setValue(id, value);
                    if (param.onchange !== undefined) {
                        param.onchange(obj[cfield]);
                    }

                    // store the value to localstorage
                };
                return func;
            })();
        },

        getCallbackName: function(name, prgId) {
            return 'change_'+prgId+"_"+name;
        },

        copyDefaultValue: function(param) {
            var uvalue = param.value;
            if (Array.isArray(param.value)) {
                uvalue = param.value.slice();
            } else {
                uvalue = [uvalue];
            }
            return uvalue;
        },

        createInternalSliderUniform: function(param) {
            var uvalue = param.value;
            var uniform = param.uniform;
            if (uniform === undefined) {
                var type = param.type;
                type = type.charAt(0).toUpperCase() + type.slice(1);
                uniform = osg.Uniform["create"+type](uvalue, param.name);
            }

            var cbname = this.getCallbackName(param.name, param.id);
            var dim = uvalue.length;
            for (var i = 0; i < dim; i++) {

                var istring = i.toString();
                var nameIndex = param.name + istring;
                var cbnameIndex = cbname+istring;

                // default value
                var value = uvalue[i];

                // read local storage value if it exist
                var readValue = this.getValue(cbnameIndex);
                if (readValue !== null) {
                    value = readValue;
                } else if (param.uniform && param.uniform.get()[i] !== undefined) {
                    // read value from original uniform
                    value = param.uniform.get()[i];
                }

                var dom = this.createHTMLSlider(param, value, nameIndex, cbnameIndex);
                this.addToDom(dom);
                window[cbnameIndex] = this.createUniformFunction(param, nameIndex, i, uniform, cbnameIndex);
                osg.log(nameIndex + " " + value);
                window[cbnameIndex](value);
            }
            this.uniform = uniform;
            return uniform;
        },

        createInternalSlider: function(param) {
            var uvalue = param.value;
            var name = param.name;
            var id = param.id;
            var dim = uvalue.length;
            var cbname = this.getCallbackName(name, id);
            var object = param.object;
            var field = param.field;
            for (var i = 0; i < dim; i++) {

                var istring = i.toString();
                var nameIndex = name + istring;
                var cbnameIndex = cbname+istring;

                // default value
                var value = uvalue[i];

                // read local storage value if it exist
                var readValue = this.getValue(cbnameIndex);
                if (readValue !== null) {
                    value = readValue;
                } else {
                    if (typeof object[field] === 'number') {
                        value = object[field];
                    } else {
                        value = object[field][i];
                    }
                }

                var dom = this.createHTMLSlider(param, value, nameIndex, cbnameIndex);
                this.addToDom(dom);
                window[cbnameIndex] = this.createFunction(param, nameIndex, i, object, field, cbnameIndex);
                osg.log(nameIndex + " " + value);
                window[cbnameIndex](value);
            }
        },

        createSlider: function(param) {
            if (param.html !== undefined) {
                this.setTargetHTML(param.html);
            }
            if (param.id === undefined) {
                param.id = param.name;
            }
            param.value = this.copyDefaultValue(param);
            if (param.type !== undefined) {
                return this.createInternalSliderUniform(param);
            } else {
                if (param.object === undefined) {
                    param.object = {'data': param.value };
                    param.field = 'data';
                }
                return this.createInternalSlider(param);
            }
        }
    };

osgUtil.ParameterVisitor = function() {
    osg.NodeVisitor.call(this);

    this.arraySlider = new ArraySlider();
    this.setTargetHTML(document.body);
};

osgUtil.ParameterVisitor.createSlider = function(param) {
    (new ArraySlider()).createSlider(param);
};

osgUtil.ParameterVisitor.prototype = osg.objectInehrit(osg.NodeVisitor.prototype, {

    setTargetHTML: function(html) {
        this.targetHTML = html;
        this.arraySlider.setTargetHTML(this.targetHTML);
    },

    getUniformList: function(str, map) {

      //var txt='uniform float Power; // { min: 0.1, max: 2.0, step: 0.1, value: [0,0,0]  }';

      var re1='(uniform)';	// Word 1
      var re2='.*?';	// Non-greedy match on filler
      var re3='((?:[a-z][a-z]+))';	// Word 2
      var re4='.*?';	// Non-greedy match on filler
      var re5='((?:[a-z][a-z]+))';	// Word 3
      var re6='.*?';	// Non-greedy match on filler
      var re7='.';	// Uninteresting: c
      var re8='.*?';	// Non-greedy match on filler
      var re9='.';	// Uninteresting: c
      var re10='.*?';	// Non-greedy match on filler
      var re11='(.)';	// Any Single Character 1
      var re12='(.)';	// Any Single Character 2
      var re13='.*?';	// Non-greedy match on filler
      var re14='(\\{.*?\\})';	// Curly Braces 1

      var p = new RegExp(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14,["g"]);
        var r = str.match(p);
        var list = map;
        if (r !== null) {
            var re = new RegExp(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14,["i"]);
            for (var i = 0, l = r.length; i < l; i++) {
                var result = r[i].match(re);
                //var result = p.exec(str);
                if (result !== null) {
                    var word1=result[1];
                    var type=result[2];
                    var name=result[3];
                    var c1=result[4];
                    var c2=result[5];
                    var json=result[6];

                    var param = JSON.parse(json);
                    param.type = type;
                    param.name = name;
                    var value = param.value;
                    param.value = function() { return value; };
                    list[name] = param;
                }
            }
        }
        return list;
    },

    getUniformFromStateSet: function(stateSet, uniformMap) {
        var maps = stateSet.getUniformList();
        if (!maps) {
            return;
        }
        var keys = Object.keys(uniformMap);
        for (var i = 0, l = keys.length; i < l; i++) {
            var k = keys[i];
            // get the first one found in the tree
            if (maps[k] !== undefined && uniformMap[k].uniform === undefined) {
                uniformMap[k].uniform = maps[k].object;
            }
        }
    },

    findExistingUniform: function(node, uniformMap) {
        var BackVisitor = function() { osg.NodeVisitor.call(this, osg.NodeVisitor.TRAVERSE_PARENTS); };
        BackVisitor.prototype = osg.objectInehrit(osg.NodeVisitor.prototype, {
            setUniformMap: function(map) { this.uniformMap = map; },
            apply: function(node) {
                var stateSet = node.getStateSet();
                if (stateSet) {
                    osgUtil.ParameterVisitor.prototype.getUniformFromStateSet(stateSet, this.uniformMap);
                }
                this.traverse(node);
            }
        });
        var visitor = new BackVisitor();
        visitor.setUniformMap(uniformMap);
        node.accept(visitor);
    },

    applyProgram: function(node, stateset) {
        var program = stateset.getAttribute('Program');
        var programName = program.getName();
        var string = program.getVertexShader().getText();
        var uniformMap = {};
        this.getUniformList(program.getVertexShader().getText(), uniformMap);
        this.getUniformList(program.getFragmentShader().getText(), uniformMap);

        var keys = Object.keys(uniformMap);

        if (programName === undefined) {
            var hashCode = function(str) {
	        var hash = 0;
                var char = 0;
	        if (str.length == 0) return hash;
	        for (i = 0; i < str.length; i++) {
		    char = str.charCodeAt(i);
		    hash = ((hash<<5)-hash)+char;
		    hash = hash & hash; // Convert to 32bit integer
	        }
                if (hash < 0) {
                    hash = -hash;
                }
	        return hash;
            }
            var str = keys.join('');
            programName = hashCode(str).toString();
        }

        this.findExistingUniform(node, uniformMap);

        var addedSlider = false;
        for (var i = 0; i < keys.length; i++) {
            var k = keys[i];
            var entry = uniformMap[k];
            var type = entry.type;
            var name = entry.name;
            entry.id = programName;
            var uniform = this.arraySlider.createSlider(entry);
            if (false) {
                var uniform = this.arraySlider.createSlider(
                    { name: name,
                      type: type,
                      id: programName,
                      uniform: entry.uniform
                    }
                );
            }
            if (entry.uniform === undefined && uniform) {
                stateset.addUniform(uniform);
            }
            addedSlider = true;
        }

        // add a separator
        if (addedSlider) {
            var mydiv = document.createElement('div');
            mydiv.innerHTML = "

";
            this.targetHTML.appendChild(mydiv);
        }

        osg.log(uniformMap);
    },

    applyStateSet: function(node, stateset) {
        if (stateset.getAttribute('Program') !== undefined) {
            this.applyProgram(node, stateset);
        }
    },

    apply: function(node) {
        var element = this.targetHTML;
        if (element === undefined || element === null) {
            return;
        }

        var st = node.getStateSet();
        if (st !== undefined) {
            this.applyStateSet(node, st);
        }

        this.traverse(node);
    }
});

})();<commit_msg>Reindent code<commit_after>/** -*- compile-command: "jslint-cli ShaderParameterVisitor.js" -*-
 * Authors:
 *  Cedric Pinson <cedric.pinson@plopbyte.com>
 */

(function() {

    var ArraySlider = function(params) {
        if (params !== undefined) {
            if (params.object !== undefined && params.field !== undefined) {
                this.createInternalSlider(param);
            }
            this._uniform = this.createInternalSliderUniform(param);
        }
    };

    ArraySlider.prototype = {
        setTargetHTML: function(target) {
            this.parent = target;
        },
        addToDom: function(content) {
            var mydiv = document.createElement('div');
            mydiv.innerHTML = content;
            this.parent.appendChild(mydiv);
        },

        getValue: function(name) {
            if (window.localStorage) {
                var value = window.localStorage.getItem(name);
                return value;
            }
            return null;
        },
        setValue: function(name, value) {
            if (window.localStorage) {
                window.localStorage.setItem(name, value);
            }
        },
        createHTMLSlider: function(param, value, nameIndex, cbnameIndex) {
            var input = '
NAME [ MIN - MAX ] <input type="range" min="MIN" max="MAX" value="VALUE" step="STEP" onchange="ONCHANGE" />
';
            var min = param.min;
            var max = param.max;
            var step = param.step;
            var name = nameIndex;
            var cbname = cbnameIndex;
            var onchange = cbname + '(this.value)';
            input = input.replace(/MIN/g, min);
            input = input.replace(/MAX/g, (max+step));
            input = input.replace('STEP', step);
            input = input.replace('VALUE', value);
            input = input.replace(/NAME/g, name);
            input = input.replace(/UPDATE/g, cbname);
            input = input.replace('ONCHANGE', onchange);
            return input;
        },

        createUniformFunction: function(param, name, index, uniform, cbnameIndex) {
            self = this;
            return (function() {
                var cname = name;
                var cindex = index;
                var cuniform = uniform;
                var id = cbnameIndex;
                var func = function(value) {
                    cuniform.get()[cindex] = value;
                    cuniform.dirty();
                    osg.debug(cname + ' value ' + value);
                    document.getElementById(cbnameIndex).innerHTML = Number(value).toFixed(4);
                    self.setValue(id, value);
                    if (param.onchange !== undefined) {
                        param.onchange(cuniform.get());
                    }
                    // store the value to localstorage
                };
                return func;
            })();
        },

        createFunction: function(param, name, index, object, field, cbnameIndex) {
            self = this;
            return (function() {
                var cname = name;
                var cindex = index;
                var cfield = field;
                var id = cbnameIndex;
                var obj = object;
                var func = function(value) {
                    if (typeof(value) === 'string') {
                        value = parseFloat(value);
                    }

                    if (typeof(object[cfield]) === 'number') {
                        obj[cfield] = value;
                    } else {
                        obj[cfield][index] = value;
                    }
                    osg.debug(cname + ' value ' + value);
                    document.getElementById(cbnameIndex).innerHTML = Number(value).toFixed(4);
                    self.setValue(id, value);
                    if (param.onchange !== undefined) {
                        param.onchange(obj[cfield]);
                    }

                    // store the value to localstorage
                };
                return func;
            })();
        },

        getCallbackName: function(name, prgId) {
            return 'change_'+prgId+"_"+name;
        },

        copyDefaultValue: function(param) {
            var uvalue = param.value;
            if (Array.isArray(param.value)) {
                uvalue = param.value.slice();
            } else {
                uvalue = [uvalue];
            }
            return uvalue;
        },

        createInternalSliderUniform: function(param) {
            var uvalue = param.value;
            var uniform = param.uniform;
            if (uniform === undefined) {
                var type = param.type;
                type = type.charAt(0).toUpperCase() + type.slice(1);
                uniform = osg.Uniform["create"+type](uvalue, param.name);
            }

            var cbname = this.getCallbackName(param.name, param.id);
            var dim = uvalue.length;
            for (var i = 0; i < dim; i++) {

                var istring = i.toString();
                var nameIndex = param.name + istring;
                var cbnameIndex = cbname+istring;

                // default value
                var value = uvalue[i];

                // read local storage value if it exist
                var readValue = this.getValue(cbnameIndex);
                if (readValue !== null) {
                    value = readValue;
                } else if (param.uniform && param.uniform.get()[i] !== undefined) {
                    // read value from original uniform
                    value = param.uniform.get()[i];
                }

                var dom = this.createHTMLSlider(param, value, nameIndex, cbnameIndex);
                this.addToDom(dom);
                window[cbnameIndex] = this.createUniformFunction(param, nameIndex, i, uniform, cbnameIndex);
                osg.log(nameIndex + " " + value);
                window[cbnameIndex](value);
            }
            this.uniform = uniform;
            return uniform;
        },

        createInternalSlider: function(param) {
            var uvalue = param.value;
            var name = param.name;
            var id = param.id;
            var dim = uvalue.length;
            var cbname = this.getCallbackName(name, id);
            var object = param.object;
            var field = param.field;
            for (var i = 0; i < dim; i++) {

                var istring = i.toString();
                var nameIndex = name + istring;
                var cbnameIndex = cbname+istring;

                // default value
                var value = uvalue[i];

                // read local storage value if it exist
                var readValue = this.getValue(cbnameIndex);
                if (readValue !== null) {
                    value = readValue;
                } else {
                    if (typeof object[field] === 'number') {
                        value = object[field];
                    } else {
                        value = object[field][i];
                    }
                }

                var dom = this.createHTMLSlider(param, value, nameIndex, cbnameIndex);
                this.addToDom(dom);
                window[cbnameIndex] = this.createFunction(param, nameIndex, i, object, field, cbnameIndex);
                osg.log(nameIndex + " " + value);
                window[cbnameIndex](value);
            }
        },

        createSlider: function(param) {
            if (param.html !== undefined) {
                this.setTargetHTML(param.html);
            }
            if (param.id === undefined) {
                param.id = param.name;
            }
            param.value = this.copyDefaultValue(param);
            if (param.type !== undefined) {
                return this.createInternalSliderUniform(param);
            } else {
                if (param.object === undefined) {
                    param.object = {'data': param.value };
                    param.field = 'data';
                }
                return this.createInternalSlider(param);
            }
        }
    };

osgUtil.ParameterVisitor = function() {
    osg.NodeVisitor.call(this);

    this.arraySlider = new ArraySlider();
    this.setTargetHTML(document.body);
};

osgUtil.ParameterVisitor.createSlider = function(param) {
    (new ArraySlider()).createSlider(param);
};

osgUtil.ParameterVisitor.prototype = osg.objectInehrit(osg.NodeVisitor.prototype, {

    setTargetHTML: function(html) {
        this.targetHTML = html;
        this.arraySlider.setTargetHTML(this.targetHTML);
    },

    getUniformList: function(str, map) {

      //var txt='uniform float Power; // { min: 0.1, max: 2.0, step: 0.1, value: [0,0,0]  }';

      var re1='(uniform)';	// Word 1
      var re2='.*?';	// Non-greedy match on filler
      var re3='((?:[a-z][a-z]+))';	// Word 2
      var re4='.*?';	// Non-greedy match on filler
      var re5='((?:[a-z][a-z]+))';	// Word 3
      var re6='.*?';	// Non-greedy match on filler
      var re7='.';	// Uninteresting: c
      var re8='.*?';	// Non-greedy match on filler
      var re9='.';	// Uninteresting: c
      var re10='.*?';	// Non-greedy match on filler
      var re11='(.)';	// Any Single Character 1
      var re12='(.)';	// Any Single Character 2
      var re13='.*?';	// Non-greedy match on filler
      var re14='(\\{.*?\\})';	// Curly Braces 1

      var p = new RegExp(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14,["g"]);
        var r = str.match(p);
        var list = map;
        if (r !== null) {
            var re = new RegExp(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14,["i"]);
            for (var i = 0, l = r.length; i < l; i++) {
                var result = r[i].match(re);
                //var result = p.exec(str);
                if (result !== null) {
                    var word1=result[1];
                    var type=result[2];
                    var name=result[3];
                    var c1=result[4];
                    var c2=result[5];
                    var json=result[6];

                    var param = JSON.parse(json);
                    param.type = type;
                    param.name = name;
                    var value = param.value;
                    param.value = function() { return value; };
                    list[name] = param;
                }
            }
        }
        return list;
    },

    getUniformFromStateSet: function(stateSet, uniformMap) {
        var maps = stateSet.getUniformList();
        if (!maps) {
            return;
        }
        var keys = Object.keys(uniformMap);
        for (var i = 0, l = keys.length; i < l; i++) {
            var k = keys[i];
            // get the first one found in the tree
            if (maps[k] !== undefined && uniformMap[k].uniform === undefined) {
                uniformMap[k].uniform = maps[k].object;
            }
        }
    },

    findExistingUniform: function(node, uniformMap) {
        var BackVisitor = function() { osg.NodeVisitor.call(this, osg.NodeVisitor.TRAVERSE_PARENTS); };
        BackVisitor.prototype = osg.objectInehrit(osg.NodeVisitor.prototype, {
            setUniformMap: function(map) { this.uniformMap = map; },
            apply: function(node) {
                var stateSet = node.getStateSet();
                if (stateSet) {
                    osgUtil.ParameterVisitor.prototype.getUniformFromStateSet(stateSet, this.uniformMap);
                }
                this.traverse(node);
            }
        });
        var visitor = new BackVisitor();
        visitor.setUniformMap(uniformMap);
        node.accept(visitor);
    },

    applyProgram: function(node, stateset) {
        var program = stateset.getAttribute('Program');
        var programName = program.getName();
        var string = program.getVertexShader().getText();
        var uniformMap = {};
        this.getUniformList(program.getVertexShader().getText(), uniformMap);
        this.getUniformList(program.getFragmentShader().getText(), uniformMap);

        var keys = Object.keys(uniformMap);

        if (programName === undefined) {
            var hashCode = function(str) {
                var hash = 0;
                var chara = 0;
                if (str.length === 0) {
                    return hash;
                }
                for (i = 0; i < str.length; i++) {
                    chara = str.charCodeAt(i);
                    hash = ((hash<<5)-hash)+chara;
                    hash = hash & hash; // Convert to 32bit integer
                }
                if (hash < 0) {
                    hash = -hash;
                }
                return hash;
            };
            var str = keys.join('');
            programName = hashCode(str).toString();
        }

        this.findExistingUniform(node, uniformMap);

        var addedSlider = false;
        for (var i = 0; i < keys.length; i++) {
            var k = keys[i];
            var entry = uniformMap[k];
            var type = entry.type;
            var name = entry.name;
            entry.id = programName;
            var uniform = this.arraySlider.createSlider(entry);
            if (false) {
                var uniform = this.arraySlider.createSlider(
                    { name: name,
                      type: type,
                      id: programName,
                      uniform: entry.uniform
                    }
                );
            }
            if (entry.uniform === undefined && uniform) {
                stateset.addUniform(uniform);
            }
            addedSlider = true;
        }

        // add a separator
        if (addedSlider) {
            var mydiv = document.createElement('div');
            mydiv.innerHTML = "

";
            this.targetHTML.appendChild(mydiv);
        }

        osg.log(uniformMap);
    },

    applyStateSet: function(node, stateset) {
        if (stateset.getAttribute('Program') !== undefined) {
            this.applyProgram(node, stateset);
        }
    },

    apply: function(node) {
        var element = this.targetHTML;
        if (element === undefined || element === null) {
            return;
        }

        var st = node.getStateSet();
        if (st !== undefined) {
            this.applyStateSet(node, st);
        }

        this.traverse(node);
    }
});

})();<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { findDOMNode } from 'react-dom'
import Popover from 'material-ui/Popover/Popover'
import TextField from 'material-ui/TextField/TextField'
import Menu from 'material-ui/Menu/Menu'
import MenuItem from 'material-ui/MenuItem/MenuItem'
import SelectionsPresenter from './SelectionsPresenter'
import UnCheckedIcon from 'material-ui/svg-icons/toggle/check-box-outline-blank'

class SelectField extends Component {
  componentWillMount () {
    this.setState({ isOpen: false, searchText: '' })
  }

  // for debugging/styling purposes, set this to null
  // to disable list autoclosing on clickAway
  closeMenu () {
    this.setState({ isOpen: false, searchText: '' }, () => {
      findDOMNode(this.root).focus()
    })
  }

  openMenu () {
    this.setState({ isOpen: true }, () => {
      this.focusTextField()
    })
  }

  clearTextField (callback) {
    this.setState({ searchText: '' }, callback)
  }

  focusTextField () {
    if (this.props.children.length > 10) {
      const input = findDOMNode(this.searchTextField).getElementsByTagName('input')[0]
      input.focus()
    }
  }

  focusFirstMenuItem () {
    const firstMenuItem = findDOMNode(this.menu).querySelector('[tabindex="0"]')
    firstMenuItem.focus()
  }

  focusLastMenuItem () {
    const menuItems = findDOMNode(this.menu).querySelectorAll('[tabindex]')
    const lastMenuItem = menuItems[menuItems.length - 1]
    lastMenuItem.focus()
  }

  /**
   * Main Component Wrapper methods
   */
  handleClick = () => {
    this.openMenu() // toggle instead of close ? (in case user changes  targetOrigin/anchorOrigin)
  }

  handleKeyDown = (event) => {
    if (/ArrowDown|Enter/.test(event.key)) this.openMenu()
  }

  /**
   * Popover methods
   */
  handlePopoverClose = (reason) => {
    this.closeMenu() // toggle instead of close ? (in case user changes targetOrigin/anchorOrigin)
  }

  /**
   * SelectionPresenter methods
   */
  handleTextFieldAutocompletionFiltering = (event, searchText) => {
    this.setState({ searchText }, () => this.focusTextField())
  }

  handleTextFieldKeyDown= (event) => {
    switch (event.key) {
      case 'ArrowDown':
        this.focusFirstMenuItem()
        break

      case 'Escape':
        this.clearTextField()
        this.closeMenu()
        break

      default: break
    }
  }

  /**
   * Menu methods
   */
  handleMenuSelection = (event, selectedMenuItem) => {
    const { multiple, onSelect, name } = this.props
    onSelect(selectedMenuItem, name)
    multiple
      ? this.clearTextField(() => this.focusTextField())
      : this.closeMenu()
  }

  handleMenuEscKeyDown = () => this.closeMenu()

  handleMenuKeyDown= (event) => {
    // TODO: this solution propagates and triggers double onKeyDown
    // if event.stopPropagation(), nothing works, so the correct trigger is the 2nd one
    switch (event.key) {
      case 'ArrowUp':
        // TODO: add Shift+Tab
        // TODO: add if current MenuItem === firstChild
        this.focusTextField()
        break

      case 'ArrowDown':
        // TODO: if current MenuItem === lastChild, this.focusFirstMenuItem()
        break

      case 'PageUp':
        // TODO: this.focusFirstMenuItem()
        break

      case 'PageDown':
        // TODO: this.focusLastMenuItem()
        this.focusLastMenuItem()
        break

      default: break
    }
  }

  render () {
    const { value, hintText, multiple, children, style, menuProps,
      autocompleteFilter, displaySelectionsRenderer } = this.props
    const menuItems = this.state.isOpen && children &&
      children.map((child, index) => {
        if (!autocompleteFilter(this.state.searchText, child.props.label)) return // eslint-disable-line
        const isSelected = value.includes(child.props.value)
        return (
          <MenuItem
            key={index}
            tabIndex={index}
            value={child.props.value}
            checked={multiple && isSelected}
            leftIcon={(multiple && !isSelected) ? <UnCheckedIcon /> : null}
            primaryText={child}
            disableFocusRipple
            innerDivStyle={{ paddingTop: 5, paddingBottom: 5 }}
          />)
      })

    // TODO: set autoWidth to false automatically if width prop has a value
    const menuWidth = this.root ? this.root.clientWidth : null

    // TODO: check rendering performance with 200 MenuItems (integrate react-virtualized ?)

    // TODO: add props.disableAutoComplete (default: false)

    // TODO: implement a checkboxRenderer for MenuItem (or expose 2 properties CheckIconFalse & CheckIconTrue)

    // TODO: make SelectionsPresenter appears only if current numMenuItems > this.maxMenuItems

    // TODO: add a css rule for this.root :focus { outline: 'none' }, and :hover { darken }

    return (
      <div
        ref={ref => (this.root = ref)}
        tabIndex='0'
        style={{ cursor: 'pointer', // eslint-disable-line object-property-newline
          // border: '1px dashed red', borderBottom: 'none', // eslint-disable-line object-property-newline
          ...style }} // eslint-disable-line object-property-newline
        onKeyDown={this.handleKeyDown}
        onClick={this.handleClick}
        onBlur={this.handleBlur}
      >

        <SelectionsPresenter
          hintText={hintText}
          value={value}
          displaySelectionsRenderer={displaySelectionsRenderer}
        />

        <Popover
          open={this.state.isOpen}
          anchorEl={this.root}
          canAutoPosition={false}
          anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
          useLayerForClickAway={false}
          onRequestClose={this.handlePopoverClose}
        >
          {children.length > 10 &&
          <TextField
            name='autoComplete'
            ref={ref => (this.searchTextField = ref)}
            value={this.state.searchText}
            hintText={hintText}
            onChange={this.handleTextFieldAutocompletionFiltering}
            onKeyDown={this.handleTextFieldKeyDown}
            style={{ marginLeft: 16, marginBottom: -8, width: menuWidth - 16 * 2 }}
          />
          }
          <Menu
            ref={ref => (this.menu = ref)}
            {...menuProps}
            value={value}
            multiple={multiple}
            initiallyKeyboardFocused
            onChange={this.handleMenuSelection}
            onEscKeyDown={this.handleMenuEscKeyDown}
            onKeyDown={this.handleMenuKeyDown}
            desktop
            autoWidth={false}
            width={menuWidth}
          >
            {menuItems}
          </Menu>
        </Popover>

      </div>
    )
  }
}

SelectField.propTypes = {
  style: PropTypes.object,
  menuProps: PropTypes.object,
  children: PropTypes.any,
  value: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.arrayOf(PropTypes.string),
    PropTypes.object,
    PropTypes.arrayOf(PropTypes.object)
  ]),
  autocompleteFilter: PropTypes.func,
  displaySelectionsRenderer: PropTypes.func,
  name: PropTypes.string,
  hintText: PropTypes.string,
  multiple: PropTypes.bool,
  disableSearch: PropTypes.bool,
  onSelect: PropTypes.func
}

// noinspection JSUnusedGlobalSymbols
SelectField.defaultProps = {
  multiple: false,
  disableSearch: false,
  autoComplete: false,
  // eslint-disable-next-line no-unused-vars
  autocompleteFilter: (searchText, text) => {
    return !text || text.toLowerCase().includes(searchText.toLowerCase())
  }
}

export default SelectField
<commit_msg>Added 'No match found' when Autocomplete returns null<commit_after>import React, { Component, PropTypes } from 'react'
import { findDOMNode } from 'react-dom'
import Popover from 'material-ui/Popover/Popover'
import TextField from 'material-ui/TextField/TextField'
import Menu from 'material-ui/Menu/Menu'
import MenuItem from 'material-ui/MenuItem/MenuItem'
import SelectionsPresenter from './SelectionsPresenter'
import UnCheckedIcon from 'material-ui/svg-icons/toggle/check-box-outline-blank'

class SelectField extends Component {
  componentWillMount () {
    this.setState({ isOpen: false, searchText: '' })
  }

  // for debugging/styling purposes, set this to null
  // to disable list autoclosing on clickAway
  closeMenu () {
    this.setState({ isOpen: false, searchText: '' }, () => {
      findDOMNode(this.root).focus()
    })
  }

  openMenu () {
    this.setState({ isOpen: true }, () => {
      this.focusTextField()
    })
  }

  clearTextField (callback) {
    this.setState({ searchText: '' }, callback)
  }

  focusTextField () {
    if (this.props.children.length > 10) {
      const input = findDOMNode(this.searchTextField).getElementsByTagName('input')[0]
      input.focus()
    }
  }

  focusFirstMenuItem () {
    const firstMenuItem = findDOMNode(this.menu).querySelector('[tabindex="0"]')
    firstMenuItem.focus()
  }

  focusLastMenuItem () {
    const menuItems = findDOMNode(this.menu).querySelectorAll('[tabindex]')
    const lastMenuItem = menuItems[menuItems.length - 1]
    lastMenuItem.focus()
  }

  /**
   * Main Component Wrapper methods
   */
  handleClick = () => {
    this.openMenu() // toggle instead of close ? (in case user changes  targetOrigin/anchorOrigin)
  }

  handleKeyDown = (event) => {
    if (/ArrowDown|Enter/.test(event.key)) this.openMenu()
  }

  /**
   * Popover methods
   */
  handlePopoverClose = (reason) => {
    this.closeMenu() // toggle instead of close ? (in case user changes targetOrigin/anchorOrigin)
  }

  /**
   * SelectionPresenter methods
   */
  handleTextFieldAutocompletionFiltering = (event, searchText) => {
    this.setState({ searchText }, () => this.focusTextField())
  }

  handleTextFieldKeyDown= (event) => {
    switch (event.key) {
      case 'ArrowDown':
        this.focusFirstMenuItem()
        break

      case 'Escape':
        this.clearTextField()
        this.closeMenu()
        break

      default: break
    }
  }

  /**
   * Menu methods
   */
  handleMenuSelection = (event, selectedMenuItem) => {
    const { multiple, onSelect, name } = this.props
    onSelect(selectedMenuItem, name)
    multiple
      ? this.clearTextField(() => this.focusTextField())
      : this.closeMenu()
  }

  handleMenuEscKeyDown = () => this.closeMenu()

  handleMenuKeyDown= (event) => {
    // TODO: this solution propagates and triggers double onKeyDown
    // if event.stopPropagation(), nothing works, so the correct trigger is the 2nd one
    switch (event.key) {
      case 'ArrowUp':
        // TODO: add Shift+Tab
        // TODO: add if current MenuItem === firstChild
        this.focusTextField()
        break

      case 'ArrowDown':
        // TODO: if current MenuItem === lastChild, this.focusFirstMenuItem()
        break

      case 'PageUp':
        // TODO: this.focusFirstMenuItem()
        break

      case 'PageDown':
        // TODO: this.focusLastMenuItem()
        this.focusLastMenuItem()
        break

      default: break
    }
  }

  render () {
    const { value, hintText, multiple, children, style, menuProps,
      autocompleteFilter, displaySelectionsRenderer } = this.props
    const menuItems = this.state.isOpen && children &&
      children.reduce((nodes, child, index) => {
        if (!autocompleteFilter(this.state.searchText, child.props.label)) return nodes
        const isSelected = value.includes(child.props.value)
        return [ ...nodes, (
          <MenuItem
            key={index}
            tabIndex={index}
            value={child.props.value}
            checked={multiple && isSelected}
            leftIcon={(multiple && !isSelected) ? <UnCheckedIcon /> : null}
            primaryText={child}
            disableFocusRipple
            innerDivStyle={{ paddingTop: 5, paddingBottom: 5 }}
          />)]
      }, [])

    // TODO: set autoWidth to false automatically if width prop has a value
    const menuWidth = this.root ? this.root.clientWidth : null

    // TODO: check rendering performance with 200 MenuItems (integrate react-virtualized ?)

    // TODO: add props.disableAutoComplete (default: false)

    // TODO: implement a checkboxRenderer for MenuItem (or expose 2 properties CheckIconFalse & CheckIconTrue)

    // TODO: make SelectionsPresenter appears only if current numMenuItems > this.maxMenuItems

    // TODO: add a css rule for this.root :focus { outline: 'none' }, and :hover { darken }

    return (
      <div
        ref={ref => (this.root = ref)}
        tabIndex='0'
        style={{ cursor: 'pointer', // eslint-disable-line object-property-newline
          // border: '1px dashed red', borderBottom: 'none', // eslint-disable-line object-property-newline
          ...style }} // eslint-disable-line object-property-newline
        onKeyDown={this.handleKeyDown}
        onClick={this.handleClick}
        onBlur={this.handleBlur}
      >

        <SelectionsPresenter
          hintText={hintText}
          value={value}
          displaySelectionsRenderer={displaySelectionsRenderer}
        />

        <Popover
          open={this.state.isOpen}
          anchorEl={this.root}
          canAutoPosition={false}
          anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
          useLayerForClickAway={false}
          onRequestClose={this.handlePopoverClose}
        >
          {children.length > 10 &&
            <TextField
              name='autoComplete'
              ref={ref => (this.searchTextField = ref)}
              value={this.state.searchText}
              hintText={hintText}
              onChange={this.handleTextFieldAutocompletionFiltering}
              onKeyDown={this.handleTextFieldKeyDown}
              style={{ marginLeft: 16, width: menuWidth - 16 * 2 }}
            />
          }
          <Menu
            ref={ref => (this.menu = ref)}
            {...menuProps}
            value={value}
            multiple={multiple}
            initiallyKeyboardFocused
            onChange={this.handleMenuSelection}
            onEscKeyDown={this.handleMenuEscKeyDown}
            onKeyDown={this.handleMenuKeyDown}
            desktop
            autoWidth={false}
            width={menuWidth}
          >
            {menuItems.length
              ? menuItems
              : <MenuItem primaryText='No match found' disabled />
            }
          </Menu>
        </Popover>

      </div>
    )
  }
}

SelectField.propTypes = {
  style: PropTypes.object,
  menuProps: PropTypes.object,
  children: PropTypes.any,
  value: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.arrayOf(PropTypes.string),
    PropTypes.object,
    PropTypes.arrayOf(PropTypes.object)
  ]),
  autocompleteFilter: PropTypes.func,
  displaySelectionsRenderer: PropTypes.func,
  name: PropTypes.string,
  hintText: PropTypes.string,
  multiple: PropTypes.bool,
  disableSearch: PropTypes.bool,
  onSelect: PropTypes.func
}

// noinspection JSUnusedGlobalSymbols
SelectField.defaultProps = {
  multiple: false,
  disableSearch: false,
  autoComplete: false,
  // eslint-disable-next-line no-unused-vars
  autocompleteFilter: (searchText, text) => !text || text.toLowerCase().includes(searchText.toLowerCase())
}

export default SelectField
<|endoftext|>


<commit_before>// $(document).ready(function(){
//     $('.vDateField').datepicker();
//     $('.vTimeField').clockpick({
//         starthour: 0,
//         endhour: 23,
//         showminutes: true,
//         minutedivisions: 4,
//         military: true,
//     });
// });

// Inserts shortcut buttons after all of the following:
//     <input type="text" class="vDateField">
//     <input type="text" class="vTimeField">

var DateTimeShortcuts = {
    calendars: [],
    calendarInputs: [],
    clockInputs: [],
    calendarDivName1: 'calendarbox', // name of calendar
 that gets toggled
    calendarDivName2: 'calendarin',  // name of
 that contains calendar
    calendarLinkName: 'calendarlink',// name of the link that is used to toggle
    clockDivName: 'clockbox',        // name of clock
 that gets toggled
    clockLinkName: 'clocklink',      // name of the link that is used to toggle
    admin_media_prefix: '',
    init: function() {
        // Deduce admin_media_prefix by looking at the


<commit_before>// 42: array - `Array.prototype.keys`
// To do: make all tests pass, leave the assert lines unchanged!

describe('`Array.prototype.keys` returns an iterator for all keys in the array', () => {

  it('`keys()` returns an iterator', function() {
    const arr = ['a', 'b'];
    const iterator = arr.keys();

    assert.deepEqual(iterator.next(), {value: 0, done: false});
    assert.deepEqual(iterator.next(), {value: 1, done: false});
    assert.deepEqual(iterator.next(), {value: void 0, done: true});
  });

  it('gets all keys', function() {
    const arr = [1, 2, 3];
    const keys = Array.from(arr.keys());

    assert.deepEqual(keys, [0, 1, 2]);
  });

  it('empty array contains no keys', function() {
    const arr = [];
    const keys = [...arr.keys()];

    assert.equal(keys.length, 0);
  });

  it('a sparse array without real values has keys though', function() {
    const arr = [,,];
    const keys = [...arr.keys()];

    assert.deepEqual(keys, [0, 1]);
  });

  it('also includes holes in sparse arrays', function() {
    const arr = ['a', , 'c'];
    const keys = Array.from(arr.keys());

    assert.deepEqual(keys, [0, 1, 2]);
  });
});
<commit_msg>Simple but effective kata, I think.<commit_after>// 42: array - `Array.prototype.keys`
// To do: make all tests pass, leave the assert lines unchanged!

describe('`Array.prototype.keys` returns an iterator for all keys in the array', () => {

  it('`keys()` returns an iterator', function() {
    const arr = ['a', 'b'];
    const iterator = arr.keys();

    assert.deepEqual(iterator.next(), {value: 0, done: false});
    assert.deepEqual(iterator.next(), {value: void 0, done: true});
  });

  it('gets all keys', function() {
    const arr = [1, 2];
    const keys = Array.from(arr.keys());

    assert.deepEqual(keys, [0, 1, 2]);
  });

  it('empty array contains no keys', function() {
    const arr = ['empty me'];
    const keys = [...arr.keys()];

    assert.equal(keys.length, 0);
  });

  it('a sparse array without real values has keys though', function() {
    const arr = [,,];
    const keys = [...arr.___()];

    assert.deepEqual(keys, [0, 1]);
  });

  it('also includes holes in sparse arrays', function() {
    const arr = ['a', , 'c'];
    const keys = arr.keys;

    assert.deepEqual(keys, [0, 1, 2]);
  });
});
<|endoftext|>


<commit_before>// 22: class - creation
// To do: make all tests pass, leave the assert lines unchanged!

describe('class creation', () => {

  it('is as simple as `class XXX {}`', function() {
    let TestClass;

    const instance = new TestClass();
    assert.equal(typeof instance, 'object');
  });

  it('class is block scoped', () => {
    class Inside {}
    {class Inside {}}
    assert.equal(typeof Inside, 'undefined');
  });

  it('special method is `constructor`', function() {
    class User {
      constructor(id) {}
    }

    const user = new User(42);
    assert.equal(user.id, 42);
  });

  it('defining a method is simple', function() {
    class User {
    }

    const notATester = new User();
    assert.equal(notATester.writesTests(), false);
  });

  it('multiple methods need no commas (opposed to object notation)', function() {
    class User {
      wroteATest() { this.everWroteATest = true; }
      isLazy() {  }
    }

    const tester = new User();
    assert.equal(tester.isLazy(), true);
    tester.wroteATest();
    assert.equal(tester.isLazy(), false);
  });

  it('anonymous class', () => {
    const classType = typeof {};
    assert.equal(classType, 'function');
  });

});

<commit_msg>Kataify and improve test descriptions.<commit_after>// 22: class - creation
// To do: make all tests pass, leave the assert lines unchanged!

describe('Class creation', () => {
  it('is as simple as `class XXX {}`', function() {
    //// let TestClass;
    class TestClass {}
    const instance = new TestClass();
    assert.equal(typeof instance, 'object');
  });
  it('a class is block scoped', () => {
    //// class Inside {}

    {class Inside {}}
    assert.equal(typeof Inside, 'undefined');
  });
  it('the `constructor` is a special method', function() {
    class User {
      //// constructor(id) {}
      constructor(id) { this.id = id; }
    }
    const user = new User(42);
    assert.equal(user.id, 42);
  });
  it('defining a method by writing it inside the class body', function() {
    class User {
      ////
      writesTests() { return false; }
    }
    const notATester = new User();
    assert.equal(notATester.writesTests(), false);
  });
  it('multiple methods need no commas (opposed to object notation)', function() {
    class User {
      wroteATest() { this.everWroteATest = true; }
      //// isLazy() {  }
      isLazy() { return !this.everWroteATest; }
    }
    const tester = new User();
    assert.equal(tester.isLazy(), true);
    tester.wroteATest();
    assert.equal(tester.isLazy(), false);
  });
  it('anonymous class', () => {
    //// const classType = typeof {};
    const classType = typeof class {};
    assert.equal(classType, 'function');
  });
});
<|endoftext|>


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

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

import Header from '../_TableHeader';
import Content from '../_TableContent';
import Footer from '../_TableFooter';
import Pagination from '../_TablePagination';
import CircularLoading from '../CircularLoading';

import Theme from '../Theme';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import Calculation from '../_vendors/Calculation';
import ComponentUtil from '../_vendors/ComponentUtil';

class Table extends Component {

    static Theme = Theme;
    static Align = HorizontalAlign;
    static Fixed = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            init: props.hasInitFadeOut,
            sorting: props.sorting,
            pagination: props.pagination,
            expandRows: props.expandRows,
            value: Calculation.getInitValue(props)
        };

    }

    /**
     * keep table loading after do first render
     */
    handleInit = () => {
        this.state.init && this.setState({
            init: false
        });
    };

    /**
     * handle selection change
     */
    handleChange = (value, rowIndex) => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value, rowIndex);
        });
    };

    /**
     * handle sort change
     */
    handleSortChange = sorting => {
        this.setState({
            sorting
        }, () => {
            const {onSortChange} = this.props;
            onSortChange && onSortChange(sorting);
        });
    };

    /**
     * handle pagination change
     */
    handlePaginationChange = pagination => {
        this.setState({
            pagination
        }, () => {
            const {onPaginationChange} = this.props;
            onPaginationChange && onPaginationChange(pagination);
        });
    };

    /**
     * handle expand change
     */
    handleExpandChange = expandRows => {
        this.setState({
            expandRows
        }, () => {
            const {onExpandChange} = this.props;
            onExpandChange && onExpandChange(expandRows);
        });
    };

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            sorting: ComponentUtil.getDerivedState(props, state, 'sorting'),
            pagination: ComponentUtil.getDerivedState(props, state, 'pagination'),
            expandRows: ComponentUtil.getDerivedState(props, state, 'expandRows'),
            value: Calculation.getInitValue({
                value: ComponentUtil.getDerivedState(props, state, 'value'),
                selectMode: props.selectMode
            })
        };
    }

    render() {

        const {
                className, style, isPaginated, pageSizes,
                ...restProps
            } = this.props,
            {init, sorting, pagination, expandRows, value} = this.state;

        return (

                {/* table header, display when select */}

                {/* table area */}
                <Content {...restProps}
                         sorting={sorting}
                         pagination={pagination}
                         expandRows={expandRows}
                         value={value}
                         isPaginated={isPaginated}
                         onInit={this.handleInit}
                         onChange={this.handleChange}
                         onSortChange={this.handleSortChange}
                         onExpandChange={this.handleExpandChange}/>

                {/* table footer */}

                {/* table pagination */}
                {
                    isPaginated ?
                        <Pagination {...restProps}
                                    pagination={pagination}
                                    pageSizes={pageSizes}
                                    value={value}
                                    onChange={this.handlePaginationChange}/>
                        :
                        null
                }

                    {
                        init ?
                            <CircularLoading className="table-init-loading"/>
                            :
                            null
                    }

        );

    }
}

Table.propTypes = {

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

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

    /**
     * The theme of the table select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The select mode of table.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * The select all mode of table, all or current page.
     */
    selectAllMode: PropTypes.oneOf(Util.enumerateValue(SelectAllMode)),

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( true / 'left' / 'right' )
         */
        fixed: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(Util.enumerateValue(HorizontalAlign))]),

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.array,
    idProp: PropTypes.string,
    disabled: PropTypes.bool,
    hasInitFadeOut: PropTypes.bool,
    expandRows: PropTypes.array,

    /**
     * multi select checkbox icon
     */
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),
    defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType)),
    sortingAscIconCls: PropTypes.string,
    sortingDescIconCls: PropTypes.string,
    sortingFunc: PropTypes.func,

    /**
     * pagination
     */
    isPaginated: PropTypes.bool,
    pagination: PropTypes.shape({
        pageSize: PropTypes.number,
        page: PropTypes.number
    }),
    pageSizes: PropTypes.array,
    useFullPagination: PropTypes.bool,

    /**
     * fixed
     */
    isHeadFixed: PropTypes.bool,
    isFootFixed: PropTypes.bool,

    /**
     * scroll
     */
    scroll: PropTypes.shape({
        width: PropTypes.number,
        height: PropTypes.number
    }),

    /**
     * callback
     */
    hasChildren: PropTypes.func,
    onChange: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onSelectAll: PropTypes.func,
    onDeselectAll: PropTypes.func,
    onExpand: PropTypes.func,
    onCollapse: PropTypes.func,
    onExpandChange: PropTypes.func,
    onSortChange: PropTypes.func,
    onPaginationChange: PropTypes.func

};

Table.defaultProps = {

    selectMode: SelectMode.SINGLE_SELECT,
    selectAllMode: SelectAllMode.CURRENT_PAGE,

    disabled: false,
    hasInitFadeOut: true,
    expandRows: [],

    uncheckedIconCls: 'far fa-square',
    checkedIconCls: 'fas fa-check-square',
    indeterminateIconCls: 'fas fa-minus-square',

    defaultSortingType: SortingType.ASC,
    sortingAscIconCls: 'fas fa-angle-up',
    sortingDescIconCls: 'fas fa-angle-down',

    isPaginated: true,
    pagination: {
        pageSize: 10,
        page: 0
    },
    pageSizes: [5, 10, 15, 20],
    useFullPagination: false,

    isHeadFixed: false,
    isFootFixed: false

};

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

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

import Header from '../_TableHeader';
import Content from '../_TableContent';
import Footer from '../_TableFooter';
import Pagination from '../_TablePagination';
import CircularLoading from '../CircularLoading';

import Theme from '../Theme';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import Calculation from '../_vendors/Calculation';
import ComponentUtil from '../_vendors/ComponentUtil';

class Table extends Component {

    static Theme = Theme;
    static Align = HorizontalAlign;
    static Fixed = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            init: props.hasInitFadeOut,
            sorting: props.sorting,
            pagination: props.pagination,
            expandRows: props.expandRows,
            value: Calculation.getInitValue(props)
        };

    }

    /**
     * keep table loading after do first render
     */
    handleInit = () => {
        this.state.init && this.setState({
            init: false
        });
    };

    /**
     * handle selection change
     */
    handleChange = (value, rowIndex) => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value, rowIndex);
        });
    };

    /**
     * handle sort change
     */
    handleSortChange = sorting => {
        this.setState({
            sorting
        }, () => {
            const {onSortChange} = this.props;
            onSortChange && onSortChange(sorting);
        });
    };

    /**
     * handle pagination change
     */
    handlePaginationChange = pagination => {
        this.setState({
            pagination
        }, () => {
            const {onPaginationChange} = this.props;
            onPaginationChange && onPaginationChange(pagination);
        });
    };

    /**
     * handle expand change
     */
    handleExpandChange = (expandRows, callback) => {
        this.setState({
            expandRows
        }, () => {
            const {onExpandChange} = this.props;
            onExpandChange && onExpandChange(expandRows);
            callback && callback();
        });
    };

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            sorting: ComponentUtil.getDerivedState(props, state, 'sorting'),
            pagination: ComponentUtil.getDerivedState(props, state, 'pagination'),
            expandRows: ComponentUtil.getDerivedState(props, state, 'expandRows'),
            value: Calculation.getInitValue({
                value: ComponentUtil.getDerivedState(props, state, 'value'),
                selectMode: props.selectMode
            })
        };
    }

    render() {

        const {
                className, style, isPaginated, pageSizes,
                ...restProps
            } = this.props,
            {init, sorting, pagination, expandRows, value} = this.state;

        return (

                {/* table header, display when select */}

                {/* table area */}
                <Content {...restProps}
                         sorting={sorting}
                         pagination={pagination}
                         expandRows={expandRows}
                         value={value}
                         isPaginated={isPaginated}
                         onInit={this.handleInit}
                         onChange={this.handleChange}
                         onSortChange={this.handleSortChange}
                         onExpandChange={this.handleExpandChange}/>

                {/* table footer */}

                {/* table pagination */}
                {
                    isPaginated ?
                        <Pagination {...restProps}
                                    pagination={pagination}
                                    pageSizes={pageSizes}
                                    value={value}
                                    onChange={this.handlePaginationChange}/>
                        :
                        null
                }

                    {
                        init ?
                            <CircularLoading className="table-init-loading"/>
                            :
                            null
                    }

        );

    }
}

Table.propTypes = {

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

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

    /**
     * The theme of the table select radio or checkbox.
     */
    selectTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The select mode of table.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * The select all mode of table, all or current page.
     */
    selectAllMode: PropTypes.oneOf(Util.enumerateValue(SelectAllMode)),

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * fixed position of column ( true / 'left' / 'right' )
         */
        fixed: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(Util.enumerateValue(HorizontalAlign))]),

        /**
         * width of column
         */
        width: PropTypes.number,

        /**
         * minimum width of column
         */
        minWidth: PropTypes.number,

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table header
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * align of table body cell
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table body
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * column span of table foot
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,

    data: PropTypes.array,
    idProp: PropTypes.string,
    disabled: PropTypes.bool,
    hasInitFadeOut: PropTypes.bool,
    expandRows: PropTypes.array,

    /**
     * multi select checkbox icon
     */
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * sorting
     */
    sorting: PropTypes.shape({
        prop: PropTypes.string,
        type: PropTypes.oneOf(Util.enumerateValue(SortingType))
    }),
    defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType)),
    sortingAscIconCls: PropTypes.string,
    sortingDescIconCls: PropTypes.string,
    sortingFunc: PropTypes.func,

    /**
     * pagination
     */
    isPaginated: PropTypes.bool,
    pagination: PropTypes.shape({
        pageSize: PropTypes.number,
        page: PropTypes.number
    }),
    pageSizes: PropTypes.array,
    useFullPagination: PropTypes.bool,

    /**
     * fixed
     */
    isHeadFixed: PropTypes.bool,
    isFootFixed: PropTypes.bool,

    /**
     * scroll
     */
    scroll: PropTypes.shape({
        width: PropTypes.number,
        height: PropTypes.number
    }),

    /**
     * callback
     */
    hasChildren: PropTypes.func,
    onChange: PropTypes.func,
    onSelect: PropTypes.func,
    onDeselect: PropTypes.func,
    onSelectAll: PropTypes.func,
    onDeselectAll: PropTypes.func,
    onExpand: PropTypes.func,
    onCollapse: PropTypes.func,
    onExpandChange: PropTypes.func,
    onSortChange: PropTypes.func,
    onPaginationChange: PropTypes.func

};

Table.defaultProps = {

    selectMode: SelectMode.SINGLE_SELECT,
    selectAllMode: SelectAllMode.CURRENT_PAGE,

    disabled: false,
    hasInitFadeOut: true,
    expandRows: [],

    uncheckedIconCls: 'far fa-square',
    checkedIconCls: 'fas fa-check-square',
    indeterminateIconCls: 'fas fa-minus-square',

    defaultSortingType: SortingType.ASC,
    sortingAscIconCls: 'fas fa-angle-up',
    sortingDescIconCls: 'fas fa-angle-down',

    isPaginated: true,
    pagination: {
        pageSize: 10,
        page: 0
    },
    pageSizes: [5, 10, 15, 20],
    useFullPagination: false,

    isHeadFixed: false,
    isFootFixed: false

};

export default Table;
<|endoftext|>