<commit_before>function main() {
    // X-HTTP-Method-Override browser compatibility workaround
    Backbone.emulateHTTP = true;

    // base class for all widgets
    var BaseWidget = Backbone.View.extend({
        options: {
            _widget: {}
        },
        getWidgetOptions: function() {
            return this.options._widget.options || {};
        },
        setWidgetOptions: function(widgetOptions) {
            this.options._widget.options = widgetOptions;
        },
        getDatasource: function() {
            return this.options._widget.datasource || null;
        },
        setDatasource: function(url) {
            var settings = {};
            if (Backbone.emulateHTTP) {
                settings.type = 'POST';
                settings.headers = {'X-HTTP-Method-Override': 'OPTIONS'};
            } else {
                settings.type = 'OPTIONS';
            }
            settings.dataType = 'json';
            settings.async = false;

            var jqXHR = $.ajax(url, settings);
            var datasourceOptions = $.parseJSON(jqXHR.responseText);

            if (datasourceOptions.series != this.model.get('series') ||
                datasourceOptions.dimensions != this.model.get('dimensions'))
                throw 'datasource options mismatch';

            this.options._widget.datasource = url;
        },
        getWidgetData: function(settings) {
            var datasource = this.getDatasource();
            if (!datasource)
                throw 'datasource not configured';

            settings = settings || {};
            settings.dataType = 'json';

            return $.ajax(datasource, settings);
        },
    });

    // widget definition persistence
    var WidgetDefinition = Backbone.Model.extend({
        // idAttribute does not play well with isNew()
        // className attribute conflicts with Backbone's
        defaults: {
            'name': 'new widget',
            'description': 'this is a new widget',
            'series': 1,
            'dimensions': 1,
            'widgetClass': 'newWidget',
            'parentClass': '',
            'source': [
                '{',
                '    getData: function(settings) {',
                '        /* override this method to adapt data to your format */',
                '        var widgetOptions = this.getWidgetOptions();',
                '        return newWidget.prototype.getData.apply(this, arguments);',
                '    },',
                '    render: function() {',
                '        /* draw widget */',
                '        var widgetOptions = this.getWidgetOptions();',
                '        var widgetData    = this.getWidgetData();',
                '        this.$el.html("new widget");',
                '        return this;',
                '    },',
                '}',
            ].join('\n'),
        },
        url: function() {
            if (this.isNew())
                return 'ws/widget-definition';
            else
                return 'ws/widget-definition/' + this.id;
        },
    });
    var WidgetDefinitionList = Backbone.Collection.extend({
        model: WidgetDefinition,
        url: 'ws/widget-definition',
        asTree: function() {
            // returns collection as nested arrays based on parentClass
            var collection = this;

            var constructNodes = function(parentClass) {
                var children = collection.filter(function(model) {
                    return model.get('parentClass') == parentClass;
                });

                return _.chain(children)
                    .sortBy(function(model) {
                        return model.get('widgetClass');
                    }).map(function(model) {
                        return {
                            model: model,
                            children: constructNodes(model.get('widgetClass')),
                        };
                    }).value();
            };

            return constructNodes();
        }
    });

    // list of available widgets view
    var WidgetLibraryView = Backbone.View.extend({
        el: $('#widget-library'),
        template: _.template($('#widget-library-tpl').html()),

        render: function() {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            view.$el.html(view.template({
                models: collection,
                currentModel: model
            }));
            return view;
        },
    });

    // widget editor view
    var WidgetEditorView = Backbone.View.extend({
        el: $('#widget-editor'),
        template: _.template($('#widget-editor-tpl').html()),

        events: {
            'change input':    'updateModel',
            'change textarea': 'updateModel',
            'change select':   'updateModel',
            'click input[type="button"]': 'updateDB',
        },

        render: function() {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var processNodes = function(nodes, depth) {
                // transforms nested arrays into flat array with depth
                flatNodes = [];

                for (var i=0; i<nodes.length; i++) {
                    var node = nodes[i];

                    flatNodes.push({
                        model: node.model,
                        depth: depth,
                    });

                    if (node.children.length)
                        flatNodes = flatNodes.concat(processNodes(node.children, depth+1));
                }

                return flatNodes;
            };

            // render template
            view.$el.html(view.template({
                models: collection,
                currentModel: model
            }));
            // fill-out select_widget
            $('select', view.$el).html('<option value="">BaseWidget</option>'+
                _.map(processNodes(collection.asTree(), 1), function(node) {
                    var currentModel = node.model;
                    var widgetClass = currentModel.get('widgetClass');
                    var depth = node.depth;

                    return '<option value="'+widgetClass+'" '+((widgetClass==model.get('parentClass'))? 'selected' : '')+' style="text-indent: '+depth+'em;">'+widgetClass+'</option>';
                }).join('')
            );

            var editor = ace.edit('editor');
            var session = editor.getSession();
            session.setMode('ace/mode/javascript');
            session.setUseSoftTabs(true);
            session.setUseWrapMode(false);
            session.setUseWorker(false); // disable syntax checker

            session.on('change', function(e) {
                model.set('source', editor.getValue());
                view.updatePreview();
            });
            editor.setValue(model.get('source'));
            editor.clearSelection();

            view.options.editor = editor;
            return view;
        },

        updateModel: function(e) {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var $target = $(e.target);
            if ($target.attr('name')) {
                console.log($target.attr('name'), $target.val());
                if ($target.attr('type') == 'checkbox')
                    model.set($target.attr('name'), $target.attr('checked') == 'checked');
                else
                    model.set($target.attr('name'), $target.val());
            }
        },

        updateDB: function(e) {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var $target = $(e.target);
            switch ($target.attr('value')) {
            case 'save':
                model.save(null, {
                    success: function() {
                        collection.fetch({
                            success: function() {
                                workspace.navigate(model.id.toString(), {trigger: true});
                            },
                        });
                    },
                });
                break;
            case 'delete':
                model.destroy({
                    success: function() {
                        collection.fetch({
                            success: function() {
                                workspace.navigate('', {trigger: true});
                            },
                        });
                    },
                });
                break;
            }
        },

        updatePreview: function() {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var source = model.get('source');
            var cfg = {};
            var data = {};

            try {
                var options = (new Function('return '+source+';'))();
                var DynamicView = BaseWidget.extend(options);
                var widget_preview = new DynamicView({
                    el: $('#widget-preview'),
                    model: model
                });
                var series = [
                    ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'].join('|')
                ].join(',')
                widget_preview.setDatasource('http://127.0.0.1:5000/ds/test?series='+series+'&dimensions=1');
                widget_preview.render();
            } catch(e) {
                $('#widget-preview').html('
'+_.escape(e)+'
');
            }
        },
    });

    // instances
    var widget_collection = new WidgetDefinitionList();
    var widget_library = new WidgetLibraryView({
        collection: widget_collection,
    });

    var widget_editor = new WidgetEditorView({
        collection: widget_collection,
    });

    // routes
    var Workspace = Backbone.Router.extend({
        routes: {
            '':          'loadWidget',
            ':widgetId': 'loadWidget',
        },

        loadWidget: function(widgetId) {
            if (widgetId)
                var model = widget_collection.get(widgetId); //TODO validation
            else
                var model = new WidgetDefinition();

            widget_library.model = model;
            widget_library.render();

            widget_editor.model = model;
            widget_editor.render();
        },
    });
    var workspace = new Workspace();

    // load widget data - fire route afterwards (calls render)
    widget_collection.fetch({
        success: function() {
            Backbone.history.start();
        },
    });
};
<commit_msg>adding defaultWidgetOptions / View inheritance<commit_after>function main() {
    // X-HTTP-Method-Override browser compatibility workaround
    Backbone.emulateHTTP = true;

    // base class for all widgets
    var BaseWidget = Backbone.View.extend({
        initialize: function(options) {
            Backbone.View.prototype.initialize.apply(this, arguments);
            this.setWidgetOptions(this.defaultWidgetOptions);
        },
        options: {
            _widget: {}
        },
        defaultWidgetOptions: {},
        getWidgetOptions: function() {
            return this.options._widget.options || {};
        },
        setWidgetOptions: function(widgetOptions) {
            this.options._widget.options = widgetOptions;
        },
        getDatasource: function() {
            return this.options._widget.datasource || null;
        },
        setDatasource: function(url) {
            var settings = {};
            if (Backbone.emulateHTTP) {
                settings.type = 'POST';
                settings.headers = {'X-HTTP-Method-Override': 'OPTIONS'};
            } else {
                settings.type = 'OPTIONS';
            }
            settings.dataType = 'json';
            settings.async = false;

            var jqXHR = $.ajax(url, settings);
            var datasourceOptions = $.parseJSON(jqXHR.responseText);

            if (datasourceOptions.series != this.model.get('series') ||
                datasourceOptions.dimensions != this.model.get('dimensions'))
                throw 'datasource options mismatch';

            this.options._widget.datasource = url;
        },
        getWidgetData: function(settings) {
            var datasource = this.getDatasource();
            if (!datasource)
                throw 'datasource not configured';

            settings = settings || {};
            settings.dataType = 'json';

            return $.ajax(datasource, settings);
        },
    });

    // widget definition persistence
    var WidgetDefinition = Backbone.Model.extend({
        // idAttribute does not play well with isNew()
        // className attribute conflicts with Backbone's
        defaults: {
            'name': 'new widget',
            'description': 'this is a new widget',
            'series': 1,
            'dimensions': 1,
            'widgetClass': 'NewWidget',
            'parentClass': '',
            'source': '',
        },
        url: function() {
            if (this.isNew())
                return 'ws/widget-definition';
            else
                return 'ws/widget-definition/' + this.id;
        },
    });
    var WidgetDefinitionList = Backbone.Collection.extend({
        model: WidgetDefinition,
        url: 'ws/widget-definition',
        asTree: function() {
            // returns collection as nested arrays based on parentClass
            var collection = this;

            var constructNodes = function(parentClass) {
                var children = collection.filter(function(model) {
                    return model.get('parentClass') == parentClass;
                });

                return _.chain(children)
                    .sortBy(function(model) {
                        return model.get('widgetClass');
                    }).map(function(model) {
                        return {
                            model: model,
                            children: constructNodes(model.get('widgetClass')),
                        };
                    }).value();
            };

            return constructNodes();
        }
    });

    // list of available widgets view
    var WidgetLibraryView = Backbone.View.extend({
        el: $('#widget-library'),
        template: _.template($('#widget-library-tpl').html()),

        render: function() {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            view.$el.html(view.template({
                models: collection,
                currentModel: model
            }));
            return view;
        },
    });

    // widget editor view
    var WidgetEditorView = Backbone.View.extend({
        el: $('#widget-editor'),
        template: _.template($('#widget-editor-tpl').html()),

        events: {
            'change input':    'updateModel',
            'change textarea': 'updateModel',
            'change select':   'updateModel',
            'click input[type="button"]': 'updateDB',
        },

        render: function() {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var processNodes = function(nodes, depth) {
                // transforms nested arrays into flat array with depth
                flatNodes = [];

                for (var i=0; i<nodes.length; i++) {
                    var node = nodes[i];

                    flatNodes.push({
                        model: node.model,
                        depth: depth,
                    });

                    if (node.children.length)
                        flatNodes = flatNodes.concat(processNodes(node.children, depth+1));
                }

                return flatNodes;
            };

            // render template
            view.$el.html(view.template({
                models: collection,
                currentModel: model
            }));
            // fill-out select_widget
            $('select', view.$el).html('<option value="">BaseWidget</option>'+
                _.map(processNodes(collection.asTree(), 1), function(node) {
                    var currentModel = node.model;
                    var widgetClass = currentModel.get('widgetClass');
                    var depth = node.depth;

                    return '<option value="'+widgetClass+'" '+((widgetClass==model.get('parentClass'))? 'selected' : '')+' style="text-indent: '+depth+'em;">'+widgetClass+'</option>';
                }).join('')
            );

            var editor = ace.edit('editor');
            var session = editor.getSession();
            session.setMode('ace/mode/javascript');
            session.setUseSoftTabs(true);
            session.setUseWrapMode(false);
            session.setUseWorker(false); // disable syntax checker

            session.on('change', function(e) {
                model.set('source', editor.getValue());
                view.updatePreview();
            });
            editor.setValue(model.get('source'));
            editor.clearSelection();

            view.options.editor = editor;
            return view;
        },

        updateModel: function(e) {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var $target = $(e.target);
            if ($target.attr('name')) {
                console.log($target.attr('name'), $target.val());
                if ($target.attr('type') == 'checkbox')
                    model.set($target.attr('name'), $target.attr('checked') == 'checked');
                else
                    model.set($target.attr('name'), $target.val());
            }
        },

        updateDB: function(e) {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            var $target = $(e.target);
            switch ($target.attr('value')) {
            case 'save':
                model.save(null, {
                    success: function() {
                        collection.fetch({
                            success: function() {
                                workspace.navigate(model.id.toString(), {trigger: true});
                            },
                        });
                    },
                });
                break;
            case 'delete':
                model.destroy({
                    success: function() {
                        collection.fetch({
                            success: function() {
                                workspace.navigate('', {trigger: true});
                            },
                        });
                    },
                });
                break;
            }
        },

        updatePreview: function() {
            var view = this;
            var model = this.model;
            var collection = this.collection;

            try {
                var source = model.get('source');
                eval('var options = '+source+';');

                var NewWidget = BaseWidget.extend(options);
                var widget_preview = new NewWidget({
                    el: $('#widget-preview'),
                    model: model
                });
                var series = [
                    ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'].join('|')
                ].join(',')
                widget_preview.setDatasource('http://127.0.0.1:5000/ds/test?series='+series+'&dimensions=1');
                widget_preview.render();
            } catch(e) {
                $('#widget-preview').html('
'+_.escape(e)+'
');
            }
        },
    });

    // instances
    var widget_collection = new WidgetDefinitionList();
    var widget_library = new WidgetLibraryView({
        collection: widget_collection,
    });

    var widget_editor = new WidgetEditorView({
        collection: widget_collection,
    });

    // routes
    var Workspace = Backbone.Router.extend({
        routes: {
            '':          'loadWidget',
            ':widgetId': 'loadWidget',
        },

        loadWidget: function(widgetId) {
            if (widgetId) {
                var model = widget_collection.get(widgetId); //TODO validation
            } else {
                var model = new WidgetDefinition();
                var source = [
                    '{',
                    '    initialize: function(options) {',
                    '        BaseWidget.prototype.initialize.apply(this, arguments);',
                    '    },',
                    '    defaultWidgetOptions: {',
                    '       /* customize */',
                    '    },',
                    '    getData: function(settings) {',
                    '        /* override this method to adapt data to your format */',
                    '        var widgetOptions = this.getWidgetOptions();',
                    '        return NewWidget.prototype.getData.apply(this, arguments);',
                    '    },',
                    '    render: function() {',
                    '        /* draw widget */',
                    '        var widgetOptions = this.getWidgetOptions();',
                    '        var widgetData    = this.getWidgetData();',
                    '        this.$el.html("new widget");',
                    '        return this;',
                    '    },',
                    '}',
                ].join('\n');
                model.set('source', source);
            }

            widget_library.model = model;
            widget_library.render();

            widget_editor.model = model;
            widget_editor.render();
        },
    });
    var workspace = new Workspace();

    // load widget data - fire route afterwards (calls render)
    widget_collection.fetch({
        success: function() {
            Backbone.history.start();
        },
    });
};
<|endoftext|>


<commit_before>const CLOSE_SIZE = 20;
const ARROW_HEIGHT = 120;
const GAP_BOTTOM = 50;
const GAP_TOP = 40;

const styles = {
	// SCENE
	container: {
		backgroundColor: 'rgba(0,0,0,0.8)',
		boxSizing: 'border-box',
		height: '100%',
		left: 0,
		padding: '0 10px',
		position: 'fixed',
		textAlign: 'center',
		top: 0,
		width: '100%',
		zIndex: 1001,
	},
	content: {
		display: 'inline-block',
		margin: '0 auto',
		maxWidth: '100%',
		position: 'relative',
		verticalAlign: 'middle',
	},
	contentHeightShim: {
		display: 'inline-block',
		height: '100%',
		lineHeight: 0,
		verticalAlign: 'middle',
	},

	// IMAGES
	image: {
		boxSizing: 'border-box',
		display: 'block',
		lineHeight: 0,
		maxWidth: '100%',
		margin: '0 auto',
		paddingBottom: 50,
		paddingTop: 40,
		height: 'auto',
		width: 'auto',

		// disable user select
		WebkitTouchCallout: 'none',
		userSelect:         'none',

	},
	figure: {
		lineHeight: 1,
		minHeight: 200,
		minWidth: 300,
		margin: 0,
		textAlign: 'center',
	},
	figureShadow: {
		bottom: GAP_BOTTOM,
		boxShadow: '0 0 8px -2px rgba(0,0,0,.6)',
		display: 'block',
		height: 'auto',
		left: 0,
		position: 'absolute',
		right: 0,
		top: GAP_TOP,
		width: 'auto',
		zIndex: -1,
	},
	footer: {
		color: 'white',
		lineHeight: 1.3,
		height: GAP_BOTTOM,
		marginTop: -GAP_BOTTOM,
		paddingTop: 5,
		position: 'absolute',
		textAlign: 'left',
		top: '100%',
		left: 0,
		width: '100%',
		cursor: 'auto',
	},
	footerCount: {
		float: 'right',
		fontSize: '.85em',
		opacity: .75,
	},
	footerCaption: {
		paddingRight: 80,
	},

	// BUTTONS
	arrow: {
		background: 'none',
		border: 'none',
		cursor: 'pointer',
		outline: 'none',
		marginTop: ARROW_HEIGHT / -2,
		maxWidth: 80,
		padding: 20,
		position: 'absolute',
		top: '50%',
		height: ARROW_HEIGHT,
		width: '16%',
		zIndex: 1001,

		// disable user select
		WebkitTouchCallout: 'none',
		WebkitUserSelect:   'none',
		MozUserSelect:      'none',
		msUserSelect:       'none',
		userSelect:         'none',
	},
	arrowNext: {
		right: 0,
	},
	arrowPrev: {
		left: 0,
	},
	closeBar: {
		height: GAP_TOP,
		left: 0,
		position: 'absolute',
		textAlign: 'right',
		top: 0,
		width: '100%',
	},
	closeButton: {
		background: 'none',
		border: 'none',
		cursor: 'pointer',
		height: CLOSE_SIZE + 20,
		outline: 'none',
		padding: 10,
		position: 'relative',
		right: -10,
		top: 0,
		width: CLOSE_SIZE + 20,
	},
};

export default styles;
<commit_msg>add loading spinner to figure<commit_after>const CLOSE_SIZE = 20;
const ARROW_HEIGHT = 120;
const GAP_BOTTOM = 50;
const GAP_TOP = 40;

const styles = {
	// SCENE
	container: {
		backgroundColor: 'rgba(0,0,0,0.8)',
		boxSizing: 'border-box',
		height: '100%',
		left: 0,
		padding: '0 10px',
		position: 'fixed',
		textAlign: 'center',
		top: 0,
		width: '100%',
		zIndex: 1001,
	},
	content: {
		display: 'inline-block',
		margin: '0 auto',
		maxWidth: '100%',
		position: 'relative',
		verticalAlign: 'middle',
	},
	contentHeightShim: {
		display: 'inline-block',
		height: '100%',
		lineHeight: 0,
		verticalAlign: 'middle',
	},

	// IMAGES
	image: {
		boxSizing: 'border-box',
		display: 'block',
		lineHeight: 0,
		maxWidth: '100%',
		margin: '0 auto',
		paddingBottom: 50,
		paddingTop: 40,
		height: 'auto',
		width: 'auto',

		// disable user select
		WebkitTouchCallout: 'none',
		userSelect:         'none',

	},
	figure: {
		backgroundImage: 'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nNDhweCcgaGVpZ2h0PSc0OHB4JyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgY2xhc3M9InVpbC1kZWZhdWx0Ij48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0ibm9uZSIgY2xhc3M9ImJrIj48L3JlY3Q+PHJlY3QgIHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjZmZmZmZmJyB0cmFuc2Zvcm09J3JvdGF0ZSgwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4gIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9J29wYWNpdHknIGZyb209JzEnIHRvPScwJyBkdXI9JzFzJyBiZWdpbj0nMHMnIHJlcGVhdENvdW50PSdpbmRlZmluaXRlJy8+PC9yZWN0PjxyZWN0ICB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nI2ZmZmZmZicgdHJhbnNmb3JtPSdyb3RhdGUoMzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0nb3BhY2l0eScgZnJvbT0nMScgdG89JzAnIGR1cj0nMXMnIGJlZ2luPScwLjA4MzMzMzMzMzMzMzMzMzMzcycgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz48L3JlY3Q+PHJlY3QgIHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjZmZmZmZmJyB0cmFuc2Zvcm09J3JvdGF0ZSg2MCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+ICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSdvcGFjaXR5JyBmcm9tPScxJyB0bz0nMCcgZHVyPScxcycgYmVnaW49JzAuMTY2NjY2NjY2NjY2NjY2NjZzJyByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPjwvcmVjdD48cmVjdCAgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNmZmZmZmYnIHRyYW5zZm9ybT0ncm90YXRlKDkwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4gIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9J29wYWNpdHknIGZyb209JzEnIHRvPScwJyBkdXI9JzFzJyBiZWdpbj0nMC4yNXMnIHJlcGVhdENvdW50PSdpbmRlZmluaXRlJy8+PC9yZWN0PjxyZWN0ICB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nI2ZmZmZmZicgdHJhbnNmb3JtPSdyb3RhdGUoMTIwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4gIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9J29wYWNpdHknIGZyb209JzEnIHRvPScwJyBkdXI9JzFzJyBiZWdpbj0nMC4zMzMzMzMzMzMzMzMzMzMzcycgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz48L3JlY3Q+PHJlY3QgIHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjZmZmZmZmJyB0cmFuc2Zvcm09J3JvdGF0ZSgxNTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0nb3BhY2l0eScgZnJvbT0nMScgdG89JzAnIGR1cj0nMXMnIGJlZ2luPScwLjQxNjY2NjY2NjY2NjY2NjdzJyByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPjwvcmVjdD48cmVjdCAgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNmZmZmZmYnIHRyYW5zZm9ybT0ncm90YXRlKDE4MCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+ICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSdvcGFjaXR5JyBmcm9tPScxJyB0bz0nMCcgZHVyPScxcycgYmVnaW49JzAuNXMnIHJlcGVhdENvdW50PSdpbmRlZmluaXRlJy8+PC9yZWN0PjxyZWN0ICB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nI2ZmZmZmZicgdHJhbnNmb3JtPSdyb3RhdGUoMjEwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4gIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9J29wYWNpdHknIGZyb209JzEnIHRvPScwJyBkdXI9JzFzJyBiZWdpbj0nMC41ODMzMzMzMzMzMzMzMzM0cycgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz48L3JlY3Q+PHJlY3QgIHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjZmZmZmZmJyB0cmFuc2Zvcm09J3JvdGF0ZSgyNDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPiAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0nb3BhY2l0eScgZnJvbT0nMScgdG89JzAnIGR1cj0nMXMnIGJlZ2luPScwLjY2NjY2NjY2NjY2NjY2NjZzJyByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPjwvcmVjdD48cmVjdCAgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNmZmZmZmYnIHRyYW5zZm9ybT0ncm90YXRlKDI3MCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+ICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSdvcGFjaXR5JyBmcm9tPScxJyB0bz0nMCcgZHVyPScxcycgYmVnaW49JzAuNzVzJyByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPjwvcmVjdD48cmVjdCAgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNmZmZmZmYnIHRyYW5zZm9ybT0ncm90YXRlKDMwMCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+ICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSdvcGFjaXR5JyBmcm9tPScxJyB0bz0nMCcgZHVyPScxcycgYmVnaW49JzAuODMzMzMzMzMzMzMzMzMzNHMnIHJlcGVhdENvdW50PSdpbmRlZmluaXRlJy8+PC9yZWN0PjxyZWN0ICB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nI2ZmZmZmZicgdHJhbnNmb3JtPSdyb3RhdGUoMzMwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4gIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9J29wYWNpdHknIGZyb209JzEnIHRvPScwJyBkdXI9JzFzJyBiZWdpbj0nMC45MTY2NjY2NjY2NjY2NjY2cycgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz48L3JlY3Q+PC9zdmc+)',
		backgroundRepeat: 'no-repeat',
		backgroundPosition: 'center center',
		lineHeight: 1,
		minHeight: 200,
		minWidth: 300,
		margin: 0,
		textAlign: 'center',
	},
	figureShadow: {
		bottom: GAP_BOTTOM,
		boxShadow: '0 0 8px -2px rgba(0,0,0,.6)',
		display: 'block',
		height: 'auto',
		left: 0,
		position: 'absolute',
		right: 0,
		top: GAP_TOP,
		width: 'auto',
		zIndex: -1,
	},
	footer: {
		color: 'white',
		lineHeight: 1.3,
		height: GAP_BOTTOM,
		marginTop: -GAP_BOTTOM,
		paddingTop: 5,
		position: 'absolute',
		textAlign: 'left',
		top: '100%',
		left: 0,
		width: '100%',
		cursor: 'auto',
	},
	footerCount: {
		float: 'right',
		fontSize: '.85em',
		opacity: .75,
	},
	footerCaption: {
		paddingRight: 80,
	},

	// BUTTONS
	arrow: {
		background: 'none',
		border: 'none',
		cursor: 'pointer',
		outline: 'none',
		marginTop: ARROW_HEIGHT / -2,
		maxWidth: 80,
		padding: 20,
		position: 'absolute',
		top: '50%',
		height: ARROW_HEIGHT,
		width: '16%',
		zIndex: 1001,

		// disable user select
		WebkitTouchCallout: 'none',
		WebkitUserSelect:   'none',
		MozUserSelect:      'none',
		msUserSelect:       'none',
		userSelect:         'none',
	},
	arrowNext: {
		right: 0,
	},
	arrowPrev: {
		left: 0,
	},
	closeBar: {
		height: GAP_TOP,
		left: 0,
		position: 'absolute',
		textAlign: 'right',
		top: 0,
		width: '100%',
	},
	closeButton: {
		background: 'none',
		border: 'none',
		cursor: 'pointer',
		height: CLOSE_SIZE + 20,
		outline: 'none',
		padding: 10,
		position: 'relative',
		right: -10,
		top: 0,
		width: CLOSE_SIZE + 20,
	},
};

export default styles;
<|endoftext|>


<commit_before>/* filterwizard Plugin
 * Depends:
 *    ui.core.js
 *     ui.view.js
 *
*/
/*global jQuery:true NB$:true */
(function($) {
    var $str        = "NB$" in window ? "NB$" : "jQuery";
    var V_OBJ = $.extend({},$.ui.view.prototype,{
        _create: function() {
            $.ui.view.prototype._create.call(this);
            var self = this;
            self.element.addClass("filterWizard");
            self._model = null;
            self._render();
        },
        _defaultHandler: function(evt){
            this._render();
        },
        _render: function(){
            var self=this;
            self.element.empty();

            var $h = $("
Filter Threads…
");
            var $e = $("
").addClass("error-message");
            var $p = $("
");

            self.element.append($h).append($e).append($p);

            // Basic Idea:
            // The controls for these text fields are:
            //  - $n : number (raw or %, according to $r)
            //  - $r : ratio? (either "percentage" or "total")
            //  - $filterType : type of filter ["random", "reply", "students", "longest"]

            var $n = $("<input>").attr("type", "text").addClass("filter-number").val(10);
            var $r = $("<select>")
                .append("<option value='threads'>threads</option>")
                .append("<option value='percent'>% of all threads</option>");
            var $filterType = $("<select>")
                .append("<option value='random'>randomly</option>")
                .append("<option value='reply'>that have the most responses</option>")
                .append("<option value='students'>that have the most student participation</option>")
                .append("<option value='longest'>that have the longest initial post</option>");
            var $go = $("<input>").attr("type", "button").attr("value", "Go");

            $p.append("Show me ")
                .append($n).append(" ")
                .append($r).append(" ")
                .append($filterType).append(". ")
                .append($go);

            $go.click(function() {
                // Step 1: validate [formatting + n/r compatibility]
                var n = parseInt($n.val(), 10);
                var r = $r.val();
                var filterType = $filterType.val();

                if (isNan(n) || n < 0) {
                    $n.addClass("input-error");
                    $e.text("You must enter a valid number or percentage of posts.");
                    return;
                }

                if (r === "precent") {
                    if (n > 100) {
                        $n.addClass("input-error");
                        $e.text("You must enter a valid percentage between 0 and 100.");
                        return;
                     }
                } else if (r === "threads") {
                    // any thread-specific checking
                } else {
                    $r.addClass("input-error");
                    $e.text("You must choose a valid quantity.");
                    return;
                }

                // Step 2: fire event
                $.concierge.trigger({
                    type: "filter_threads",
                    value: {
                        n: n,
                        r: r,
                        type: filterType
                    }
                });

                // Step 3: call callback if set
                if (self.options.callbacks.onOk) {
                    self.options.callbacks.onOk();
                }

            });

        },
        set_model: function(model){
            var self=this;
            self._model = model;
            model.register(
                $.ui.view.prototype.get_adapter.call(this),
                {
                    file: null,
                    folder: null,
                    file_stats: null,
                    replyrating: null,
                    question: null
                });

        },
        update: function(action, payload, items_fieldname){

        }
    });

    $.widget("ui.filterWizard",V_OBJ );
    $.ui.filterWizard.prototype.options = {
	listens: {
	},
	admin: false,
        callbacks: {
            onOk: null
        }
    };
})(jQuery);
<commit_msg>Fixed isNaN typo<commit_after>/* filterwizard Plugin
 * Depends:
 *    ui.core.js
 *     ui.view.js
 *
*/
/*global jQuery:true NB$:true */
(function($) {
    var $str        = "NB$" in window ? "NB$" : "jQuery";
    var V_OBJ = $.extend({},$.ui.view.prototype,{
        _create: function() {
            $.ui.view.prototype._create.call(this);
            var self = this;
            self.element.addClass("filterWizard");
            self._model = null;
            self._render();
        },
        _defaultHandler: function(evt){
            this._render();
        },
        _render: function(){
            var self=this;
            self.element.empty();

            var $h = $("
Filter Threads…
");
            var $e = $("
").addClass("error-message");
            var $p = $("
");

            self.element.append($h).append($e).append($p);

            // Basic Idea:
            // The controls for these text fields are:
            //  - $n : number (raw or %, according to $r)
            //  - $r : ratio? (either "percentage" or "total")
            //  - $filterType : type of filter ["random", "reply", "students", "longest"]

            var $n = $("<input>").attr("type", "text").addClass("filter-number").val(10);
            var $r = $("<select>")
                .append("<option value='threads'>threads</option>")
                .append("<option value='percent'>% of all threads</option>");
            var $filterType = $("<select>")
                .append("<option value='random'>randomly</option>")
                .append("<option value='reply'>that have the most responses</option>")
                .append("<option value='students'>that have the most student participation</option>")
                .append("<option value='longest'>that have the longest initial post</option>");
            var $go = $("<input>").attr("type", "button").attr("value", "Go");

            $p.append("Show me ")
                .append($n).append(" ")
                .append($r).append(" ")
                .append($filterType).append(". ")
                .append($go);

            $go.click(function() {
                // Step 1: validate [formatting + n/r compatibility]
                var n = parseInt($n.val(), 10);
                var r = $r.val();
                var filterType = $filterType.val();

                if (isNaN(n) || n < 0) {
                    $n.addClass("input-error");
                    $e.text("You must enter a valid number or percentage of posts.");
                    return;
                }

                if (r === "precent") {
                    if (n > 100) {
                        $n.addClass("input-error");
                        $e.text("You must enter a valid percentage between 0 and 100.");
                        return;
                     }
                } else if (r === "threads") {
                    // any thread-specific checking
                } else {
                    $r.addClass("input-error");
                    $e.text("You must choose a valid quantity.");
                    return;
                }

                // Step 2: fire event
                $.concierge.trigger({
                    type: "filter_threads",
                    value: {
                        n: n,
                        r: r,
                        type: filterType
                    }
                });

                // Step 3: call callback if set
                if (self.options.callbacks.onOk) {
                    self.options.callbacks.onOk();
                }

            });

        },
        set_model: function(model){
            var self=this;
            self._model = model;
            model.register(
                $.ui.view.prototype.get_adapter.call(this),
                {
                    file: null,
                    folder: null,
                    file_stats: null,
                    replyrating: null,
                    question: null
                });

        },
        update: function(action, payload, items_fieldname){

        }
    });

    $.widget("ui.filterWizard",V_OBJ );
    $.ui.filterWizard.prototype.options = {
	listens: {
	},
	admin: false,
        callbacks: {
            onOk: null
        }
    };
})(jQuery);
<|endoftext|>


<commit_before>/**
* timbles.js
* definitely the most lightweight jquery table plugin ever
* except probably not
*
* @version 1.1.0
* @author jenn schiffer http://jennmoney.biz
*/

( function( $ ) {

'use strict';

var pluginName = 'timbles';

var classes = {
  disabled: 'disabled',
  active: 'active',
  sortHeader: 'timbles-sort-header',
  sortASC: 'sorted-asc',
  sortDESC: 'sorted-desc',
  noSort: 'no-sort',
  navigationCurrentPage: 'pointer-this-page',
  navigationLastPage: 'pointer-last-page',
  paginationToolsContainer: 'pagination',
  paginationNavArrows: 'nav-arrows',
  paginationNavRowCountChoice: 'row-count-choice',
  paginationNavigationButton: null,
  paginationRowCountButton: null
};

var copy = {
  firstPageArrow: ' << ',
  prevPageArrow: ' < ',
  nextPageArrow: ' > ',
  lastPageArrow: ' >> ',
  page: 'page',
  of: 'of'
};

var methods = {

  // Initialize timble, er, i mean table //
  init: function( opts ) {
    var options = $.extend( {}, opts );
    var data = {
      classes: $.extend( {}, classes, options.classes ),
      copy: $.extend( {}, copy, options.copy ),
      dataConfig: methods.parseDataConfig( options.dataConfig ),
      sorting: options.sorting,
      pagination: options.pagination
    };
    this.data( pluginName, data ).addClass( pluginName );

    if ( data.dataConfig ) {
      methods.generateTableFromJson.call( this );
    } else {
      methods.setupExistingTable.call( this );
    }
  },

  parseDataConfig: function( dataConfig ) {
    if ( !( dataConfig instanceof Object ) ) {
      return dataConfig;
    } else if ( dataConfig.hasOwnProperty( 'columns' ) ) {
      $.each( dataConfig.columns, function( index, columnConfig ) {
        if ( columnConfig.hasOwnProperty( 'dataFilter' ) &&
             !columnConfig.hasOwnProperty( 'textTransform' ) ) {

          // If a dataFilter is defined (old-style) and no textTransform,
          // use the dataFilter as textTransform
          columnConfig.textTransform = columnConfig.dataFilter;
        } else if ( !columnConfig.hasOwnProperty( 'textTransform' ) ) {

          // Add a do-nothing textTransform if none is provided
          columnConfig.textTransform = function( obj ) { return obj; };
        }
        if ( !columnConfig.hasOwnProperty( 'valueTransform' ) ) {

          // Add a do-nothing valueTransform if none is provided
          columnConfig.valueTransform = function( obj ) { return obj; };
        }
      } );
    }
    return dataConfig;
  },

  setupExistingTable: function() {
    var data = this.data( pluginName );

    // Select column headers and add column index to them
    data.$headers = this.find( 'thead th' ).each( function( index ) {
      $( this ).data( 'timbles-column-index', index );
    } );

    // Start enabling any given features
    methods.enableFeaturesSetup.call( this );
  },

  generateTableFromJson: function() {
    var data = this.data( pluginName );
    var $headerRow = $( '<tr>' ).appendTo( $( '<thead>' ).appendTo( this ) );

    // Generate header cells and create jQuery object from them
    data.$headers = $( $.map( data.dataConfig.columns, function( value, index ) {
      return $( '<th>' )
        .attr( 'id', value.id )
        .addClass( value.noSorting ? data.classes.noSort : null )
        .data( 'timbles-column-index', index )
        .text( value.label )
        .appendTo( $headerRow )
        .get( 0 );
    } ) );

    if ( $.isArray( data.dataConfig.data ) ) {

      // No need for ajax call if data is local array
      methods.generateRowsFromData.call( this, data.dataConfig.data, data.dataConfig.columns );

      // Start enabling any given features
      methods.enableFeaturesSetup.call( this );
    } else {

      // Get external json file given
      $.getJSON( data.dataConfig.data, function( json ) {
        methods.generateRowsFromData.call( this, json, data.dataConfig.columns );
      }.bind( this ) ).then( function() {

        // Start enabling any given features
        methods.enableFeaturesSetup.call( this );
      }.bind( this ) );
    }
  },

  generateRowsFromData: function( rowData, columnConfig ) {
    $.each( rowData, function( index, row ) {

      // Add rows to the current table
      var $newRow = $( '<tr>' ).appendTo( this );
      $.each( columnConfig, function( index, column ) {

        // Add cells to the current row
        var cellValue = row[ column.id ];
        $( '<td>' )
          .attr( 'data-value', column.valueTransform( cellValue ) )
          .text( column.textTransform( cellValue ) )
          .appendTo( this );
      }.bind( $newRow ) );
    }.bind( this ) );
  },

  enableFeaturesSetup: function() {
    var data = this.data( pluginName );
    data.tableRows = this.find( 'tbody tr' ).get();

    if ( data.sorting ) {
      methods.enableSorting.call( this );

      if ( data.sorting.keyId ) {
        methods.sortColumn.call( this, data.sorting.keyId, data.sorting.order );
      }
    }

    if ( data.pagination ) {
      methods.enablePagination.call( this, data.pagination.recordsPerPage );
    }
  },

  enableSorting: function() {
    var data = this.data( pluginName );
    data.$headers.not( '.' + data.classes.noSort )
      .addClass( data.classes.sortHeader )
      .on( 'click', methods.sortColumnEvent.bind( this ) );
  },

  sortColumn: function( key, order ) {

    // Sort a column identified by its key in a given order
    // If `key` is numeric, it is treated as the column index to sort
    // If `order` is not given, this will do the same as clicking the header
    if ( typeof key === 'number' ) {
      var data = this.data( pluginName );
      data.$headers.eq( key ).trigger( 'click', order );
    } else {
      this.find( '#' + key ).trigger( 'click', order );
    }
  },

  sortColumnEvent: function( event, order ) {
    var data = this.data( pluginName );

    // Determine order and update header sort classes
    var $sortHeader = $( event.target );
    var sortColumn = $sortHeader.data( 'timbles-column-index' );

    if ( !order ) {
      order = $sortHeader.hasClass( data.classes.sortASC ) ? 'desc' : 'asc';
    }
    data.$headers
      .removeClass( data.classes.sortASC )
      .removeClass( data.classes.sortDESC );
    $sortHeader.addClass( ( order === 'asc' ) ? data.classes.sortASC : data.classes.sortDESC );

    // Determine column values to actually sort by
    var sortMap = $.map( data.tableRows, function( row ) {
      var cell = row.children[ sortColumn ];
      var dataValue = cell.getAttribute( 'data-value' );
      if ( dataValue === null ) {
        dataValue = cell.textContent || cell.innerText || '';
      } else if ( parseFloat( dataValue ).toString() === dataValue ) {
        dataValue = parseFloat( dataValue );
      }
      return {
        node: row,
        value: dataValue
      };
    } );

    // Sort the mapping by the extract column values
    sortMap.sort( function( a, b ) {
      if ( a.value > b.value ) {
        return ( order === 'asc' ) ? 1 : -1;
      }
      if ( a.value < b.value ) {
        return ( order === 'asc' ) ? -1 : 1;
      }
      return 0;
    } );

    // Create new canonical row set sorted based on sortMap
    data.tableRows = $.map( sortMap, function( row ) {
      return row.node;
    } );

    if ( data.pagination ) {

      // If table was paginated, load content for first page
      methods.goToPage.call( this, 1 );
    } else {

      // If not, add sorted rows in order (on detached body for performance)
      var tableBody = this.find( 'tbody' ).detach().get( 0 );
      $.each( data.tableRows, function() {
        tableBody.appendChild( this );
      } );
      this.append( tableBody );
    }
  },

  enablePagination: function( count ) {
    var data = this.data( pluginName );

    // Without records, abandon pagination. Without pagination config, create empty
    if ( !data.tableRows || data.tableRows.length === 0 ) {
      return;
    } else if ( !data.pagination ) {
      data.pagination = {};
    }

    // Update pagination page size and count
    data.pagination.currentPage = 1;
    data.pagination.recordsPerPage = count;
    data.pagination.lastPage = Math.ceil( data.tableRows.length / count );

    // Create tools if they don't exist yet
    if ( !data.$paginationToolsContainer ) {
      methods.generatePaginationTools.call( this );
    }

    // Actually place records for the first page
    methods.goToPage.call( this, 1 );
  },

  generatePaginationTools: function() {
    var data = this.data( pluginName );

    data.$paginationToolsContainer = $( '<div>' )
      .addClass( data.classes.paginationToolsContainer )
      .insertAfter( this );

    if ( !data.pagination.nav ) {

      // If no pagination is configured, default to showing arrows only
      methods.generatePaginationNavArrows.call( this );
    } else {
      for ( var navObject in data.pagination.nav ) {
        switch ( navObject ) {
          case 'arrows':
            methods.generatePaginationNavArrows.call( this );
            break;
          case 'rowCountChoice':
            methods.generatePaginationNavRowCountChoice.call( this );
            break;
        }
      }
    }
    methods.updatePaginationTools.call( this );
  },

  generatePaginationNavArrows: function() {
    var data = this.data( pluginName );
    var $navButton = $( '<button>' )
      .attr( 'type', 'button' )
      .toggleClass(
        data.classes.paginationNavigationButton,
        data.classes.paginationNavigationButton );

    data.$linkFirstPage = $navButton.clone().text( data.copy.firstPageArrow );
    data.$linkPrevPage = $navButton.clone().text( data.copy.prevPageArrow );
    data.$linkNextPage = $navButton.clone().text( data.copy.nextPageArrow );
    data.$linkLastPage = $navButton.clone().text( data.copy.lastPageArrow );
    data.$pointerThisPage = $( '<span>' )
        .addClass( classes.navigationCurrentPage )
        .text( data.pagination.currentPage );
    data.$pointerLastPage = $( '<span>' )
        .addClass( classes.navigationLastPage )
        .text( data.pagination.lastPage );
    var $pageNumberTracker = $( '<span>' )
      .addClass( 'page-number-tracker' )
      .text( data.copy.page + ' ' )
      .append( data.$pointerThisPage )
      .append( ' ' + data.copy.of + ' ' )
      .append( data.$pointerLastPage );

    $( '<div>' )
      .addClass( data.classes.paginationNavArrows )
      .append( data.$linkFirstPage )
      .append( data.$linkPrevPage )
      .append( $pageNumberTracker )
      .append( data.$linkNextPage )
      .append( data.$linkLastPage )
      .appendTo( data.$paginationToolsContainer );

    // Register event listeners
    data.$linkFirstPage.on( 'click', function() {
      methods.goToPage.call( this, 1 );
    }.bind( this ) );

    data.$linkPrevPage.on( 'click', function() {
      if ( data.pagination.currentPage > 1 ) {
        methods.goToPage.call( this, data.pagination.currentPage - 1 );
      }
    }.bind( this ) );

    data.$linkNextPage.on( 'click', function() {
      if ( data.pagination.currentPage < data.pagination.lastPage ) {
        methods.goToPage.call( this, data.pagination.currentPage + 1 );
      }
    }.bind( this ) );

    data.$linkLastPage.on( 'click', function() {
      methods.goToPage.call( this, data.pagination.lastPage );
    }.bind( this ) );
  },

  generatePaginationNavRowCountChoice: function() {
    var pageSizeChangeEvent, pageSizeSelection;
    var data = this.data( pluginName );

    pageSizeSelection = $( '<div>' )
      .addClass( data.classes.paginationNavRowCountChoice )
      .appendTo( data.$paginationToolsContainer );

    pageSizeChangeEvent = function( event ) {
      var $target = $( event.target ).addClass( data.classes.active );
      $target.siblings().removeClass( data.classes.active );
      var pageSize = $target.text();

      if ( pageSize.toLowerCase() === 'all' ) {
        pageSize = data.tableRows.length;
      }

      methods.enablePagination.call( this, parseInt( pageSize, 10 ) );
    }.bind( this );

    $.each( data.pagination.nav.rowCountChoice, function() {
      $( '<button>' )
        .attr( 'type', 'button' )
        .on( 'click', pageSizeChangeEvent )
        .text( this )
        .toggleClass( data.classes.active, data.pagination.recordsPerPage === this )
        .toggleClass(
          data.classes.paginationRowCountButton,
          data.classes.paginationRowCountButton )
        .appendTo( pageSizeSelection );
    } );
  },

  updatePaginationTools: function() {
    var data = this.data( pluginName );

    function toggleButtons( buttons, disabled ) {
      $.each( buttons, function() {
        this.toggleClass( data.classes.disabled, disabled );
        this.attr( 'disabled', disabled );
      } );
    }

    // Set buttons inactive if appropriate
    toggleButtons(
      [ data.$linkFirstPage, data.$linkPrevPage ],
      data.pagination.currentPage === 1 );
    toggleButtons(
      [ data.$linkLastPage, data.$linkNextPage ],
      data.pagination.currentPage === data.pagination.lastPage );

    // Update page number tracker
    data.$pointerThisPage.text( data.pagination.currentPage );
    data.$pointerLastPage.text( data.pagination.lastPage );
  },

  goToPage: function( page ) {
    var data = this.data( pluginName );
    var newFirstRowNum = ( page - 1 ) * data.pagination.recordsPerPage;
    var newLastRowNum = Math.min(
      newFirstRowNum + data.pagination.recordsPerPage,
      data.tableRows.length );

    // Check for valid page number
    if ( page < 1 || page > data.pagination.lastPage ) {
      return;
    }

    // Update page number and display page's rows
    data.pagination.currentPage = page;
    this.find( 'tbody tr' ).remove();
    this.find( 'tbody' ).append(
      data.tableRows.slice( newFirstRowNum, newLastRowNum ) );

    // Update pagination tools
    methods.updatePaginationTools.call( this );
  }
};

// Install timbles jQuery plugin
$.fn[ pluginName ] = function( method ) {
  if ( $.isPlainObject( method ) || method === undefined ) {
    return this.each( function() {
      methods.init.call( $( this ), method );
    } );
  } else if ( methods.hasOwnProperty( method ) ) {
    var actualMethod = methods[ method ];
    var methodArgs = Array.prototype.slice.call( arguments, 1 );
    return this.each( function() {
      actualMethod.apply( $( this ), methodArgs );
    } );
  }
  $.error( 'The method ' + method + ' literally does not exist. Good job.' );
};

} )( jQuery );
<commit_msg>Separate column header operation from table configuration for pre-existing tables.<commit_after>/**
* timbles.js
* definitely the most lightweight jquery table plugin ever
* except probably not
*
* @version 1.1.0
* @author jenn schiffer http://jennmoney.biz
*/

( function( $ ) {

'use strict';

var pluginName = 'timbles';

var classes = {
  disabled: 'disabled',
  active: 'active',
  sortHeader: 'timbles-sort-header',
  sortASC: 'sorted-asc',
  sortDESC: 'sorted-desc',
  noSort: 'no-sort',
  navigationCurrentPage: 'pointer-this-page',
  navigationLastPage: 'pointer-last-page',
  paginationToolsContainer: 'pagination',
  paginationNavArrows: 'nav-arrows',
  paginationNavRowCountChoice: 'row-count-choice',
  paginationNavigationButton: null,
  paginationRowCountButton: null
};

var copy = {
  firstPageArrow: ' << ',
  prevPageArrow: ' < ',
  nextPageArrow: ' > ',
  lastPageArrow: ' >> ',
  page: 'page',
  of: 'of'
};

var methods = {

  // Initialize timble, er, i mean table //
  init: function( opts ) {
    var options = $.extend( {}, opts );
    var data = {
      classes: $.extend( {}, classes, options.classes ),
      copy: $.extend( {}, copy, options.copy ),
      dataConfig: methods.parseDataConfig( options.dataConfig ),
      sorting: options.sorting,
      pagination: options.pagination
    };
    this.data( pluginName, data ).addClass( pluginName );

    if ( data.dataConfig ) {
      methods.generateTableFromJson.call( this );
    } else {
      methods.configureTable.call( this );
    }
  },

  parseDataConfig: function( dataConfig ) {
    if ( !( dataConfig instanceof Object ) ) {
      return dataConfig;
    } else if ( dataConfig.hasOwnProperty( 'columns' ) ) {
      $.each( dataConfig.columns, function( index, columnConfig ) {
        if ( columnConfig.hasOwnProperty( 'dataFilter' ) &&
             !columnConfig.hasOwnProperty( 'textTransform' ) ) {

          // If a dataFilter is defined (old-style) and no textTransform,
          // use the dataFilter as textTransform
          columnConfig.textTransform = columnConfig.dataFilter;
        } else if ( !columnConfig.hasOwnProperty( 'textTransform' ) ) {

          // Add a do-nothing textTransform if none is provided
          columnConfig.textTransform = function( obj ) { return obj; };
        }
        if ( !columnConfig.hasOwnProperty( 'valueTransform' ) ) {

          // Add a do-nothing valueTransform if none is provided
          columnConfig.valueTransform = function( obj ) { return obj; };
        }
      } );
    }
    return dataConfig;
  },

  configureTable: function() {
    var data = this.data( pluginName );
    data.$headers = methods.selectColumnHeaders.call( this );

    // Start enabling any given features
    methods.enableFeaturesSetup.call( this );
  },

  selectColumnHeaders: function() {
    return this.find( 'thead th' ).each( function( index, cell ) {
      $( cell ).data( 'timbles-column-index', index );
    } );
  },

  generateTableFromJson: function() {
    var data = this.data( pluginName );
    var $headerRow = $( '<tr>' ).appendTo( $( '<thead>' ).appendTo( this ) );

    // Generate header cells and create jQuery object from them
    data.$headers = $( $.map( data.dataConfig.columns, function( value, index ) {
      return $( '<th>' )
        .attr( 'id', value.id )
        .addClass( value.noSorting ? data.classes.noSort : null )
        .data( 'timbles-column-index', index )
        .text( value.label )
        .appendTo( $headerRow )
        .get( 0 );
    } ) );

    if ( $.isArray( data.dataConfig.data ) ) {

      // No need for ajax call if data is local array
      methods.generateRowsFromData.call( this, data.dataConfig.data, data.dataConfig.columns );

      // Start enabling any given features
      methods.enableFeaturesSetup.call( this );
    } else {

      // Get external json file given
      $.getJSON( data.dataConfig.data, function( json ) {
        methods.generateRowsFromData.call( this, json, data.dataConfig.columns );
      }.bind( this ) ).then( function() {

        // Start enabling any given features
        methods.enableFeaturesSetup.call( this );
      }.bind( this ) );
    }
  },

  generateRowsFromData: function( rowData, columnConfig ) {
    $.each( rowData, function( index, row ) {

      // Add rows to the current table
      var $newRow = $( '<tr>' ).appendTo( this );
      $.each( columnConfig, function( index, column ) {

        // Add cells to the current row
        var cellValue = row[ column.id ];
        $( '<td>' )
          .attr( 'data-value', column.valueTransform( cellValue ) )
          .text( column.textTransform( cellValue ) )
          .appendTo( this );
      }.bind( $newRow ) );
    }.bind( this ) );
  },

  enableFeaturesSetup: function() {
    var data = this.data( pluginName );
    data.tableRows = this.find( 'tbody tr' ).get();

    if ( data.sorting ) {
      methods.enableSorting.call( this );

      if ( data.sorting.keyId ) {
        methods.sortColumn.call( this, data.sorting.keyId, data.sorting.order );
      }
    }

    if ( data.pagination ) {
      methods.enablePagination.call( this, data.pagination.recordsPerPage );
    }
  },

  enableSorting: function() {
    var data = this.data( pluginName );
    data.$headers.not( '.' + data.classes.noSort )
      .addClass( data.classes.sortHeader )
      .on( 'click', methods.sortColumnEvent.bind( this ) );
  },

  sortColumn: function( key, order ) {

    // Sort a column identified by its key in a given order
    // If `key` is numeric, it is treated as the column index to sort
    // If `order` is not given, this will do the same as clicking the header
    if ( typeof key === 'number' ) {
      var data = this.data( pluginName );
      data.$headers.eq( key ).trigger( 'click', order );
    } else {
      this.find( '#' + key ).trigger( 'click', order );
    }
  },

  sortColumnEvent: function( event, order ) {
    var data = this.data( pluginName );

    // Determine order and update header sort classes
    var $sortHeader = $( event.target );
    var sortColumn = $sortHeader.data( 'timbles-column-index' );

    if ( !order ) {
      order = $sortHeader.hasClass( data.classes.sortASC ) ? 'desc' : 'asc';
    }
    data.$headers
      .removeClass( data.classes.sortASC )
      .removeClass( data.classes.sortDESC );
    $sortHeader.addClass( ( order === 'asc' ) ? data.classes.sortASC : data.classes.sortDESC );

    // Determine column values to actually sort by
    var sortMap = $.map( data.tableRows, function( row ) {
      var cell = row.children[ sortColumn ];
      var dataValue = cell.getAttribute( 'data-value' );
      if ( dataValue === null ) {
        dataValue = cell.textContent || cell.innerText || '';
      } else if ( parseFloat( dataValue ).toString() === dataValue ) {
        dataValue = parseFloat( dataValue );
      }
      return {
        node: row,
        value: dataValue
      };
    } );

    // Sort the mapping by the extract column values
    sortMap.sort( function( a, b ) {
      if ( a.value > b.value ) {
        return ( order === 'asc' ) ? 1 : -1;
      }
      if ( a.value < b.value ) {
        return ( order === 'asc' ) ? -1 : 1;
      }
      return 0;
    } );

    // Create new canonical row set sorted based on sortMap
    data.tableRows = $.map( sortMap, function( row ) {
      return row.node;
    } );

    if ( data.pagination ) {

      // If table was paginated, load content for first page
      methods.goToPage.call( this, 1 );
    } else {

      // If not, add sorted rows in order (on detached body for performance)
      var tableBody = this.find( 'tbody' ).detach().get( 0 );
      $.each( data.tableRows, function() {
        tableBody.appendChild( this );
      } );
      this.append( tableBody );
    }
  },

  enablePagination: function( count ) {
    var data = this.data( pluginName );

    // Without records, abandon pagination. Without pagination config, create empty
    if ( !data.tableRows || data.tableRows.length === 0 ) {
      return;
    } else if ( !data.pagination ) {
      data.pagination = {};
    }

    // Update pagination page size and count
    data.pagination.currentPage = 1;
    data.pagination.recordsPerPage = count;
    data.pagination.lastPage = Math.ceil( data.tableRows.length / count );

    // Create tools if they don't exist yet
    if ( !data.$paginationToolsContainer ) {
      methods.generatePaginationTools.call( this );
    }

    // Actually place records for the first page
    methods.goToPage.call( this, 1 );
  },

  generatePaginationTools: function() {
    var data = this.data( pluginName );

    data.$paginationToolsContainer = $( '<div>' )
      .addClass( data.classes.paginationToolsContainer )
      .insertAfter( this );

    if ( !data.pagination.nav ) {

      // If no pagination is configured, default to showing arrows only
      methods.generatePaginationNavArrows.call( this );
    } else {
      for ( var navObject in data.pagination.nav ) {
        switch ( navObject ) {
          case 'arrows':
            methods.generatePaginationNavArrows.call( this );
            break;
          case 'rowCountChoice':
            methods.generatePaginationNavRowCountChoice.call( this );
            break;
        }
      }
    }
    methods.updatePaginationTools.call( this );
  },

  generatePaginationNavArrows: function() {
    var data = this.data( pluginName );
    var $navButton = $( '<button>' )
      .attr( 'type', 'button' )
      .toggleClass(
        data.classes.paginationNavigationButton,
        data.classes.paginationNavigationButton );

    data.$linkFirstPage = $navButton.clone().text( data.copy.firstPageArrow );
    data.$linkPrevPage = $navButton.clone().text( data.copy.prevPageArrow );
    data.$linkNextPage = $navButton.clone().text( data.copy.nextPageArrow );
    data.$linkLastPage = $navButton.clone().text( data.copy.lastPageArrow );
    data.$pointerThisPage = $( '<span>' )
        .addClass( classes.navigationCurrentPage )
        .text( data.pagination.currentPage );
    data.$pointerLastPage = $( '<span>' )
        .addClass( classes.navigationLastPage )
        .text( data.pagination.lastPage );
    var $pageNumberTracker = $( '<span>' )
      .addClass( 'page-number-tracker' )
      .text( data.copy.page + ' ' )
      .append( data.$pointerThisPage )
      .append( ' ' + data.copy.of + ' ' )
      .append( data.$pointerLastPage );

    $( '<div>' )
      .addClass( data.classes.paginationNavArrows )
      .append( data.$linkFirstPage )
      .append( data.$linkPrevPage )
      .append( $pageNumberTracker )
      .append( data.$linkNextPage )
      .append( data.$linkLastPage )
      .appendTo( data.$paginationToolsContainer );

    // Register event listeners
    data.$linkFirstPage.on( 'click', function() {
      methods.goToPage.call( this, 1 );
    }.bind( this ) );

    data.$linkPrevPage.on( 'click', function() {
      if ( data.pagination.currentPage > 1 ) {
        methods.goToPage.call( this, data.pagination.currentPage - 1 );
      }
    }.bind( this ) );

    data.$linkNextPage.on( 'click', function() {
      if ( data.pagination.currentPage < data.pagination.lastPage ) {
        methods.goToPage.call( this, data.pagination.currentPage + 1 );
      }
    }.bind( this ) );

    data.$linkLastPage.on( 'click', function() {
      methods.goToPage.call( this, data.pagination.lastPage );
    }.bind( this ) );
  },

  generatePaginationNavRowCountChoice: function() {
    var pageSizeChangeEvent, pageSizeSelection;
    var data = this.data( pluginName );

    pageSizeSelection = $( '<div>' )
      .addClass( data.classes.paginationNavRowCountChoice )
      .appendTo( data.$paginationToolsContainer );

    pageSizeChangeEvent = function( event ) {
      var $target = $( event.target ).addClass( data.classes.active );
      $target.siblings().removeClass( data.classes.active );
      var pageSize = $target.text();

      if ( pageSize.toLowerCase() === 'all' ) {
        pageSize = data.tableRows.length;
      }

      methods.enablePagination.call( this, parseInt( pageSize, 10 ) );
    }.bind( this );

    $.each( data.pagination.nav.rowCountChoice, function() {
      $( '<button>' )
        .attr( 'type', 'button' )
        .on( 'click', pageSizeChangeEvent )
        .text( this )
        .toggleClass( data.classes.active, data.pagination.recordsPerPage === this )
        .toggleClass(
          data.classes.paginationRowCountButton,
          data.classes.paginationRowCountButton )
        .appendTo( pageSizeSelection );
    } );
  },

  updatePaginationTools: function() {
    var data = this.data( pluginName );

    function toggleButtons( buttons, disabled ) {
      $.each( buttons, function() {
        this.toggleClass( data.classes.disabled, disabled );
        this.attr( 'disabled', disabled );
      } );
    }

    // Set buttons inactive if appropriate
    toggleButtons(
      [ data.$linkFirstPage, data.$linkPrevPage ],
      data.pagination.currentPage === 1 );
    toggleButtons(
      [ data.$linkLastPage, data.$linkNextPage ],
      data.pagination.currentPage === data.pagination.lastPage );

    // Update page number tracker
    data.$pointerThisPage.text( data.pagination.currentPage );
    data.$pointerLastPage.text( data.pagination.lastPage );
  },

  goToPage: function( page ) {
    var data = this.data( pluginName );
    var newFirstRowNum = ( page - 1 ) * data.pagination.recordsPerPage;
    var newLastRowNum = Math.min(
      newFirstRowNum + data.pagination.recordsPerPage,
      data.tableRows.length );

    // Check for valid page number
    if ( page < 1 || page > data.pagination.lastPage ) {
      return;
    }

    // Update page number and display page's rows
    data.pagination.currentPage = page;
    this.find( 'tbody tr' ).remove();
    this.find( 'tbody' ).append(
      data.tableRows.slice( newFirstRowNum, newLastRowNum ) );

    // Update pagination tools
    methods.updatePaginationTools.call( this );
  }
};

// Install timbles jQuery plugin
$.fn[ pluginName ] = function( method ) {
  if ( $.isPlainObject( method ) || method === undefined ) {
    return this.each( function() {
      methods.init.call( $( this ), method );
    } );
  } else if ( methods.hasOwnProperty( method ) ) {
    var actualMethod = methods[ method ];
    var methodArgs = Array.prototype.slice.call( arguments, 1 );
    return this.each( function() {
      actualMethod.apply( $( this ), methodArgs );
    } );
  }
  $.error( 'The method ' + method + ' literally does not exist. Good job.' );
};

} )( jQuery );
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2015 SAP and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * Contributors:
 * SAP - initial API and implementation
 *******************************************************************************/

/* globals $ javax */
/* eslint-env node, dirigible */

var streams = require("io/streams");

/**
 * Getter for File reference
 */
exports.get = function(path) {
	var internalFile = new java.io.File(path);
	return new File(internalFile);
};

/**
 * File object
 */
function File(internalFile) {
	this.internalFile = internalFile;
	this.getInternalObject = fileGetInternalObject;
	this.exists = fileExists;
	this.isExecutable = fileIsExecutable;
	this.isReadable = fileIsReadable;
	this.isWritable = fileIsWritable;
	this.getCanonicalPath = fileGetCanonicalPath;
	this.getPath = fileGetPath;
	this.getName = fileGetName;
	this.getParent = fileGetParent;
	this.isDirectory = fileIsDirectory;
	this.isFile = fileIsFile;
	this.isHidden = fileIsHidden;
	this.lastModified = fileLastModified;
	this.length = fileLength;
	this.list = fileList;
	this.listRoots = fileListRoots;
	this.filter = fileFilter;
	this.setExecutable = fileSetExecutable;
	this.setReadable = fileSetReadable;
	this.setWritable = fileSetWritable;
}

function fileGetInternalObject() {
	return this.internalFile;
}

function fileExists() {
	return this.internalFile.exists();
}

function fileIsExecutable() {
	return this.internalFile.canExecute();
}

function fileIsReadable() {
	return this.internalFile.canRead();
}

function fileIsWritable() {
	return this.internalFile.canWrite();
}

function fileGetCanonicalPath() {
	return this.internalFile.getCanonicalPath();
}

function fileGetPath() {
	return this.internalFile.getPath();
}

function fileGetName() {
	return this.internalFile.getName();
}

function fileGetParent() {
	return this.internalFile.getParent();
}

function fileGetParentFile() {
    if (this.internalFile.getParentFile()) {
		return new File(this.internalFile.getParentFile());
	}
	return null;
}

function fileIsDirectory() {
	return this.internalFile.isDirectory();
}

function fileIsFile() {
	return this.internalFile.isFile();
}

function fileIsHidden() {
	return this.internalFile.isHidden();
}

function fileLastModified() {
	return this.internalFile.lastModified();
}

function fileLength() {
	return this.internalFile.length();
}

function fileList() {
	var list = [];
	var internalList = this.internalFile.list();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileListRoots() {
	var list = [];
	var internalList = this.internalFile.listRoots();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileFilter(pattern) {
	var list = [];
	var filter = new java.io.FilenameFilter() {
		    accept: function(dir, name) {
		        return name.search(pattern) >= 0;
		    }
		};
	var internalList = this.internalFile.list(filter);
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileSetExecutable(executable) {
	return this.internalFile.setExecutable(executable, false);
}

function fileSetReadable(readable) {
	return this.internalFile.setReadable(readable, false);
}

function fileSetWritable(writable) {
	return this.internalFile.setWritable(writable, false);
}

/**
 * Create a new directory by a given path
 */
exports.createDirectory = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.createDirectories(internalPath);
};

/**
 * Create a new file by a given path
 */
exports.createFile = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	if (!exports.get(path).exists()) {
		java.nio.file.Files.createFile(internalPath);
	}
};

/**
 * Copy a source file to a target
 */
exports.copy = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.copy(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
};

/**
 * Move a source file to a target
 */
exports.move = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.move(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.ATOMIC_MOVE);
};

/**
 * Delete a file or an empty directory
 */
exports.delete = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.deleteIfExists(internalPath);
};

/**
 * Read a text content from a file
 */
exports.readText = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var bytes = java.nio.file.Files.readAllBytes(internalPath);
	return new java.lang.String(bytes);
};

/**
 * Write a text content to a file
 */
exports.writeText = function(path, content) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.write(internalPath, java.lang.String(content).getBytes());
};

/**
 * Read a binary content from a file
 */
exports.read = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = java.nio.file.Files.readAllBytes(internalPath);
	var bytes = streams.toJavaScriptBytes(internalBytes);
	return bytes;
};

/**
 * Write a binary content to a file
 */
exports.write = function(path, bytes) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = streams.toJavaBytes(bytes);
	java.nio.file.Files.write(internalPath, internalBytes);
};

<commit_msg>last modified fix<commit_after>/*******************************************************************************
 * Copyright (c) 2015 SAP and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * Contributors:
 * SAP - initial API and implementation
 *******************************************************************************/

/* globals $ javax */
/* eslint-env node, dirigible */

var streams = require("io/streams");

/**
 * Getter for File reference
 */
exports.get = function(path) {
	var internalFile = new java.io.File(path);
	return new File(internalFile);
};

/**
 * File object
 */
function File(internalFile) {
	this.internalFile = internalFile;
	this.getInternalObject = fileGetInternalObject;
	this.exists = fileExists;
	this.isExecutable = fileIsExecutable;
	this.isReadable = fileIsReadable;
	this.isWritable = fileIsWritable;
	this.getCanonicalPath = fileGetCanonicalPath;
	this.getPath = fileGetPath;
	this.getName = fileGetName;
	this.getParent = fileGetParent;
	this.isDirectory = fileIsDirectory;
	this.isFile = fileIsFile;
	this.isHidden = fileIsHidden;
	this.lastModified = fileLastModified;
	this.length = fileLength;
	this.list = fileList;
	this.listRoots = fileListRoots;
	this.filter = fileFilter;
	this.setExecutable = fileSetExecutable;
	this.setReadable = fileSetReadable;
	this.setWritable = fileSetWritable;
}

function fileGetInternalObject() {
	return this.internalFile;
}

function fileExists() {
	return this.internalFile.exists();
}

function fileIsExecutable() {
	return this.internalFile.canExecute();
}

function fileIsReadable() {
	return this.internalFile.canRead();
}

function fileIsWritable() {
	return this.internalFile.canWrite();
}

function fileGetCanonicalPath() {
	return this.internalFile.getCanonicalPath();
}

function fileGetPath() {
	return this.internalFile.getPath();
}

function fileGetName() {
	return this.internalFile.getName();
}

function fileGetParent() {
	return this.internalFile.getParent();
}

function fileGetParentFile() {
    if (this.internalFile.getParentFile()) {
		return new File(this.internalFile.getParentFile());
	}
	return null;
}

function fileIsDirectory() {
	return this.internalFile.isDirectory();
}

function fileIsFile() {
	return this.internalFile.isFile();
}

function fileIsHidden() {
	return this.internalFile.isHidden();
}

function fileLastModified() {
	return new Date(this.internalFile.lastModified());
}

function fileLength() {
	return this.internalFile.length();
}

function fileList() {
	var list = [];
	var internalList = this.internalFile.list();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileListRoots() {
	var list = [];
	var internalList = this.internalFile.listRoots();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileFilter(pattern) {
	var list = [];
	var filter = new java.io.FilenameFilter() {
		    accept: function(dir, name) {
		        return name.search(pattern) >= 0;
		    }
		};
	var internalList = this.internalFile.list(filter);
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileSetExecutable(executable) {
	return this.internalFile.setExecutable(executable, false);
}

function fileSetReadable(readable) {
	return this.internalFile.setReadable(readable, false);
}

function fileSetWritable(writable) {
	return this.internalFile.setWritable(writable, false);
}

/**
 * Create a new directory by a given path
 */
exports.createDirectory = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.createDirectories(internalPath);
};

/**
 * Create a new file by a given path
 */
exports.createFile = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	if (!exports.get(path).exists()) {
		java.nio.file.Files.createFile(internalPath);
	}
};

/**
 * Copy a source file to a target
 */
exports.copy = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.copy(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
};

/**
 * Move a source file to a target
 */
exports.move = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.move(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.ATOMIC_MOVE);
};

/**
 * Delete a file or an empty directory
 */
exports.delete = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.deleteIfExists(internalPath);
};

/**
 * Read a text content from a file
 */
exports.readText = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var bytes = java.nio.file.Files.readAllBytes(internalPath);
	return new java.lang.String(bytes);
};

/**
 * Write a text content to a file
 */
exports.writeText = function(path, content) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.write(internalPath, java.lang.String(content).getBytes());
};

/**
 * Read a binary content from a file
 */
exports.read = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = java.nio.file.Files.readAllBytes(internalPath);
	var bytes = streams.toJavaScriptBytes(internalBytes);
	return bytes;
};

/**
 * Write a binary content to a file
 */
exports.write = function(path, bytes) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = streams.toJavaBytes(bytes);
	java.nio.file.Files.write(internalPath, internalBytes);
};

<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2015 SAP and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * Contributors:
 * SAP - initial API and implementation
 *******************************************************************************/

/* globals $ javax */
/* eslint-env node, dirigible */

var streams = require("io/streams");

/**
 * Getter for File reference
 */
exports.get = function(path) {
	var internalFile = new java.io.File(path);
	return new File(internalFile);
};

/**
 * File object
 */
function File(internalFile) {
	this.internalFile = internalFile;
	this.getInternalObject = fileGetInternalObject;
	this.exists = fileExists;
	this.isExecutable = fileIsExecutable;
	this.isReadable = fileIsReadable;
	this.isWritable = fileIsWritable;
	this.getCanonicalPath = fileGetCanonicalPath;
	this.getPath = fileGetPath;
	this.getName = fileGetName;
	this.getParent = fileGetParent;
	this.isDirectory = fileIsDirectory;
	this.isFile = fileIsFile;
	this.isHidden = fileIsHidden;
	this.lastModified = fileLastModified;
	this.length = fileLength;
	this.list = fileList;
	this.listRoots = fileListRoots;
	this.filter = fileFilter;
	this.setExecutable = fileSetExecutable;
	this.setReadable = fileSetReadable;
	this.setWritable = fileSetWritable;
}

function fileGetInternalObject() {
	return this.internalFile;
}

function fileExists() {
	return this.internalFile.exists();
}

function fileIsExecutable() {
	return this.internalFile.canExecute();
}

function fileIsReadable() {
	return this.internalFile.canRead();
}

function fileIsWritable() {
	return this.internalFile.canWrite();
}

function fileGetCanonicalPath() {
	return this.internalFile.getCanonicalPath();
}

function fileGetPath() {
	return this.internalFile.getPath();
}

function fileGetName() {
	return this.internalFile.getName();
}

function fileGetParent() {
	return new File(this.internalFile.getParent());
}

function fileIsDirectory() {
	return this.internalFile.isDirectory();
}

function fileIsFile() {
	return this.internalFile.isFile();
}

function fileIsHidden() {
	return this.internalFile.isHidden();
}

function fileLastModified() {
	return this.internalFile.lastModified();
}

function fileLength() {
	return this.internalFile.length();
}

function fileList() {
	var list = [];
	var internalList = this.internalFile.list();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileListRoots() {
	var list = [];
	var internalList = this.internalFile.listRoots();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileFilter(pattern) {
	var list = [];
	var filter = new java.io.FilenameFilter() {
		    accept: function(dir, name) {
		        return name.search(pattern) >= 0;
		    }
		};
	var internalList = this.internalFile.list(filter);
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileSetExecutable(executable) {
	return this.internalFile.setExecutable(executable, false);
}

function fileSetReadable(readable) {
	return this.internalFile.setReadable(readable, false);
}

function fileSetWritable(writable) {
	return this.internalFile.setWritable(writable, false);
}

/**
 * Create a new directory by a given path
 */
exports.createDirectory = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.createDirectories(internalPath);
};

/**
 * Create a new file by a given path
 */
exports.createFile = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	if (!exports.get(path).exists()) {
		java.nio.file.Files.createFile(internalPath);
	}
};

/**
 * Copy a source file to a target
 */
exports.copy = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.copy(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
};

/**
 * Move a source file to a target
 */
exports.move = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.move(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.ATOMIC_MOVE);
};

/**
 * Delete a file or an empty directory
 */
exports.delete = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.deleteIfExists(internalPath);
};

/**
 * Read a text content from a file
 */
exports.readText = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var bytes = java.nio.file.Files.readAllBytes(internalPath);
	return new java.lang.String(bytes);
};

/**
 * Write a text content to a file
 */
exports.writeText = function(path, content) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.write(internalPath, java.lang.String(content).getBytes());
};

/**
 * Read a binary content from a file
 */
exports.read = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = java.nio.file.Files.readAllBytes(internalPath);
	var bytes = streams.toJavaScriptBytes(internalBytes);
	return bytes;
};

/**
 * Write a binary content to a file
 */
exports.write = function(path, bytes) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = streams.toJavaBytes(bytes);
	java.nio.file.Files.write(internalPath, internalBytes);
};

<commit_msg>files fixes<commit_after>/*******************************************************************************
 * Copyright (c) 2015 SAP and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * Contributors:
 * SAP - initial API and implementation
 *******************************************************************************/

/* globals $ javax */
/* eslint-env node, dirigible */

var streams = require("io/streams");

/**
 * Getter for File reference
 */
exports.get = function(path) {
	var internalFile = new java.io.File(path);
	return new File(internalFile);
};

/**
 * File object
 */
function File(internalFile) {
	this.internalFile = internalFile;
	this.getInternalObject = fileGetInternalObject;
	this.exists = fileExists;
	this.isExecutable = fileIsExecutable;
	this.isReadable = fileIsReadable;
	this.isWritable = fileIsWritable;
	this.getCanonicalPath = fileGetCanonicalPath;
	this.getPath = fileGetPath;
	this.getName = fileGetName;
	this.getParent = fileGetParent;
	this.isDirectory = fileIsDirectory;
	this.isFile = fileIsFile;
	this.isHidden = fileIsHidden;
	this.lastModified = fileLastModified;
	this.length = fileLength;
	this.list = fileList;
	this.listRoots = fileListRoots;
	this.filter = fileFilter;
	this.setExecutable = fileSetExecutable;
	this.setReadable = fileSetReadable;
	this.setWritable = fileSetWritable;
}

function fileGetInternalObject() {
	return this.internalFile;
}

function fileExists() {
	return this.internalFile.exists();
}

function fileIsExecutable() {
	return this.internalFile.canExecute();
}

function fileIsReadable() {
	return this.internalFile.canRead();
}

function fileIsWritable() {
	return this.internalFile.canWrite();
}

function fileGetCanonicalPath() {
	return this.internalFile.getCanonicalPath();
}

function fileGetPath() {
	return this.internalFile.getPath();
}

function fileGetName() {
	return this.internalFile.getName();
}

function fileGetParent() {
	return this.internalFile.getParent();
}

function fileGetParentFile() {
    if (this.internalFile.getParentFile()) {
		return new File(this.internalFile.getParentFile());
	}
	return null;
}

function fileIsDirectory() {
	return this.internalFile.isDirectory();
}

function fileIsFile() {
	return this.internalFile.isFile();
}

function fileIsHidden() {
	return this.internalFile.isHidden();
}

function fileLastModified() {
	return this.internalFile.lastModified();
}

function fileLength() {
	return this.internalFile.length();
}

function fileList() {
	var list = [];
	var internalList = this.internalFile.list();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileListRoots() {
	var list = [];
	var internalList = this.internalFile.listRoots();
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileFilter(pattern) {
	var list = [];
	var filter = new java.io.FilenameFilter() {
		    accept: function(dir, name) {
		        return name.search(pattern) >= 0;
		    }
		};
	var internalList = this.internalFile.list(filter);
	for (i = 0; i < internalList.length; i++) {
		list.push(internalList[i]);
	}
	return list;
}

function fileSetExecutable(executable) {
	return this.internalFile.setExecutable(executable, false);
}

function fileSetReadable(readable) {
	return this.internalFile.setReadable(readable, false);
}

function fileSetWritable(writable) {
	return this.internalFile.setWritable(writable, false);
}

/**
 * Create a new directory by a given path
 */
exports.createDirectory = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.createDirectories(internalPath);
};

/**
 * Create a new file by a given path
 */
exports.createFile = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	if (!exports.get(path).exists()) {
		java.nio.file.Files.createFile(internalPath);
	}
};

/**
 * Copy a source file to a target
 */
exports.copy = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.copy(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
};

/**
 * Move a source file to a target
 */
exports.move = function(source, target) {
	var internalSource = java.nio.file.Paths.get(source);
	var internalTarget = java.nio.file.Paths.get(target);
	java.nio.file.Files.move(internalSource, internalTarget,
		java.nio.file.StandardCopyOption.REPLACE_EXISTING,
      	java.nio.file.StandardCopyOption.ATOMIC_MOVE);
};

/**
 * Delete a file or an empty directory
 */
exports.delete = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.deleteIfExists(internalPath);
};

/**
 * Read a text content from a file
 */
exports.readText = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var bytes = java.nio.file.Files.readAllBytes(internalPath);
	return new java.lang.String(bytes);
};

/**
 * Write a text content to a file
 */
exports.writeText = function(path, content) {
	var internalPath = java.nio.file.Paths.get(path);
	java.nio.file.Files.write(internalPath, java.lang.String(content).getBytes());
};

/**
 * Read a binary content from a file
 */
exports.read = function(path) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = java.nio.file.Files.readAllBytes(internalPath);
	var bytes = streams.toJavaScriptBytes(internalBytes);
	return bytes;
};

/**
 * Write a binary content to a file
 */
exports.write = function(path, bytes) {
	var internalPath = java.nio.file.Paths.get(path);
	var internalBytes = streams.toJavaBytes(bytes);
	java.nio.file.Files.write(internalPath, internalBytes);
};

<|endoftext|>