<commit_before>module.exports = function(grunt) {

    var config = {
        themes: ['material'],
        theme: 'material',
        outputDir: '../'
    };

    require('load-grunt-tasks')(grunt);

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: config,
        browserify: {
            dist: {
                options: {
                    transform: [
                        [
                            "babelify", {
                                presets: [
                                    ['es2015', {'loose': true}]
                                ],
                                plugins: [
                                    'transform-es3-property-literals',
                                    'transform-es3-member-expression-literals'
                                ]
                            },
                        ],
                    ]
                },
                files: {
                    "../web/javascripts/application.js": ["<%= config.theme %>/javascripts/application.js"]
                }
            }
        },
        uglify: {
            dist: {
                files: {
                    '../web/javascripts/application.min.js': ['../web/javascripts/application.js']
                },
            },
            polyfill: {
                files: {
                    '../web/javascripts/polyfill.min.js': ['node_modules/ie8/build/ie8.js', 'node_modules/es5-shim/es5-shim.min.js']
                }
            }
        },
        postcss: {
          options: {
            map: true,
            processors: [
              require('autoprefixer-core')({browsers: 'last 3 versions'}),
              require('csswring')
            ]
          },
          material: {
            src: '../web/stylesheets/*.css'
          }
        },
        compass: {
            material: {
                options: {
                    sassDir: 'material/stylesheets',
                    cssDir: '../web/stylesheets',
                    imagesDir: 'material/images',
                    outputStyle: 'compressed',
                    raw: 'preferred_syntax = :sass\n'
                }
            }
        },
        copy: {
            polyfill: {
                files: [
                    {
                        src: ['node_modules/ie8/build/ie8.js'],
                        dest: '../web/javascripts/ie8.js'
                    },
                    {
                        src: ['node_modules/es5-shim/es5-shim.min.js'],
                        dest: '../web/javascripts/es5-shim.min.js'
                    }
                ]
            },
            material: {
                files: [
                    { expand: true, cwd: 'material/templates/layouts/', src: ['**'], dest: '../app/Resources/views/layouts' },
                    { expand: true, cwd: 'material/templates/modules/', src: ['**'], dest: '../app/Resources/views/modules' },
                    { expand: true, cwd: 'material/images/', src: ['**'], dest: '../web/images' },
                    { expand: true, cwd: 'bower_components/html5shiv/dist', src: ['html5shiv.min.js'], dest: '../web/javascripts' }
                ]
            }
        },
        clean: {
            options: {
                force: true
            },
            material: {
                src: [
                    '../app/Resources/views/layouts',
                    '../app/Resources/views/modules/Authentication/View',
                    '../app/Resources/views/modules/Default/View',
                    '../app/Resources/views/modules/Logout/View',
                    '../web/images/**/*',
                    '../web/javascripts/**/*',
                    '../web/stylesheets/**/*'
                ]
            },
            nonMinifiedJavaScript: {
                src: [
                    '../web/javascripts/application.js'
                ]
            }
        },
        'string-replace': {
            layoutconfig: {
                files: {
                    '../application/configs/application.ini': '../application/configs/application.ini'
                },
                options: {
                    replacements: [
                        {
                            pattern: 'defaults.layout     = "1-column-blue-grey"',
                            replacement: 'defaults.layout     = "default"'
                        }
                    ]
                }
            }
        },
        watch: {
            material: {
                files: 'material/**',
                tasks: ['theme:material']
            }
        },
        add_comment: {
            material: {
                options: {
                    comments: ["This file is generated. Please edit the files of the appropriate theme in the 'theme/' directory."],
                    syntaxes: {
                        '.phtml': ['<?php /*', '*/ ?>'],
                        '.css': ['/*', '*/']
                    }
                },
                files: [{
                    expand: true,
                    cwd: __dirname + '/..',
                    src: [
                        'app/Resources/views/layouts/**/*.phtml',
                        'app/Resources/views/modules/**/*.phtml',
                        'web/javascripts/**/*.js',
                        'wev/stylesheets/**/*.css'
                    ],
                    dest: __dirname + '/..'
                }]
            }
        }
    });

    // Default task(s).
    grunt.registerTask('default', ['theme:material']);

    grunt.registerTask('theme', 'Apply a theme to EngineBlock', function(theme){
        if (arguments.length === 0) {
            grunt.log.error('A theme name is expected; grunt theme:material');
        }

        if (config.themes.indexOf(theme) > -1) {
            // start tasks
            config.theme = theme;
            var themeConfig = JSON.parse(grunt.file.read('./config/theme.json')),
                tasks = [
                  'clean:' + themeConfig.current,
                  'copy:' + theme,
                  'compass:' + theme
                ];

            tasks.push('postcss:' + theme);
            tasks.push('browserify');
            tasks.push('uglify');
            tasks.push('clean:nonMinifiedJavaScript');
            tasks.push('add_comment:' + theme);
            tasks.push('string-replace:layoutconfig');

            grunt.task.run(tasks);

            themeConfig.current = theme;
            grunt.file.write('./config/theme.json', JSON.stringify(themeConfig));

            return true;
        }

        grunt.log.error('No such theme: ' + theme);
    });
};
<commit_msg>Remove redundant copy command in Gruntfile<commit_after>module.exports = function(grunt) {

    var config = {
        themes: ['material'],
        theme: 'material',
        outputDir: '../'
    };

    require('load-grunt-tasks')(grunt);

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: config,
        browserify: {
            dist: {
                options: {
                    transform: [
                        [
                            "babelify", {
                                presets: [
                                    ['es2015', {'loose': true}]
                                ],
                                plugins: [
                                    'transform-es3-property-literals',
                                    'transform-es3-member-expression-literals'
                                ]
                            },
                        ],
                    ]
                },
                files: {
                    "../web/javascripts/application.js": ["<%= config.theme %>/javascripts/application.js"]
                }
            }
        },
        uglify: {
            dist: {
                files: {
                    '../web/javascripts/application.min.js': ['../web/javascripts/application.js']
                },
            },
            polyfill: {
                files: {
                    '../web/javascripts/polyfill.min.js': ['node_modules/ie8/build/ie8.js', 'node_modules/es5-shim/es5-shim.min.js']
                }
            }
        },
        postcss: {
          options: {
            map: true,
            processors: [
              require('autoprefixer-core')({browsers: 'last 3 versions'}),
              require('csswring')
            ]
          },
          material: {
            src: '../web/stylesheets/*.css'
          }
        },
        compass: {
            material: {
                options: {
                    sassDir: 'material/stylesheets',
                    cssDir: '../web/stylesheets',
                    imagesDir: 'material/images',
                    outputStyle: 'compressed',
                    raw: 'preferred_syntax = :sass\n'
                }
            }
        },
        copy: {
            material: {
                files: [
                    { expand: true, cwd: 'material/templates/layouts/', src: ['**'], dest: '../app/Resources/views/layouts' },
                    { expand: true, cwd: 'material/templates/modules/', src: ['**'], dest: '../app/Resources/views/modules' },
                    { expand: true, cwd: 'material/images/', src: ['**'], dest: '../web/images' },
                    { expand: true, cwd: 'bower_components/html5shiv/dist', src: ['html5shiv.min.js'], dest: '../web/javascripts' }
                ]
            }
        },
        clean: {
            options: {
                force: true
            },
            material: {
                src: [
                    '../app/Resources/views/layouts',
                    '../app/Resources/views/modules/Authentication/View',
                    '../app/Resources/views/modules/Default/View',
                    '../app/Resources/views/modules/Logout/View',
                    '../web/images/**/*',
                    '../web/javascripts/**/*',
                    '../web/stylesheets/**/*'
                ]
            },
            nonMinifiedJavaScript: {
                src: [
                    '../web/javascripts/application.js'
                ]
            }
        },
        'string-replace': {
            layoutconfig: {
                files: {
                    '../application/configs/application.ini': '../application/configs/application.ini'
                },
                options: {
                    replacements: [
                        {
                            pattern: 'defaults.layout     = "1-column-blue-grey"',
                            replacement: 'defaults.layout     = "default"'
                        }
                    ]
                }
            }
        },
        watch: {
            material: {
                files: 'material/**',
                tasks: ['theme:material']
            }
        },
        add_comment: {
            material: {
                options: {
                    comments: ["This file is generated. Please edit the files of the appropriate theme in the 'theme/' directory."],
                    syntaxes: {
                        '.phtml': ['<?php /*', '*/ ?>'],
                        '.css': ['/*', '*/']
                    }
                },
                files: [{
                    expand: true,
                    cwd: __dirname + '/..',
                    src: [
                        'app/Resources/views/layouts/**/*.phtml',
                        'app/Resources/views/modules/**/*.phtml',
                        'web/javascripts/**/*.js',
                        'wev/stylesheets/**/*.css'
                    ],
                    dest: __dirname + '/..'
                }]
            }
        }
    });

    // Default task(s).
    grunt.registerTask('default', ['theme:material']);

    grunt.registerTask('theme', 'Apply a theme to EngineBlock', function(theme){
        if (arguments.length === 0) {
            grunt.log.error('A theme name is expected; grunt theme:material');
        }

        if (config.themes.indexOf(theme) > -1) {
            // start tasks
            config.theme = theme;
            var themeConfig = JSON.parse(grunt.file.read('./config/theme.json')),
                tasks = [
                  'clean:' + themeConfig.current,
                  'copy:' + theme,
                  'compass:' + theme
                ];

            tasks.push('postcss:' + theme);
            tasks.push('browserify');
            tasks.push('uglify');
            tasks.push('clean:nonMinifiedJavaScript');
            tasks.push('add_comment:' + theme);
            tasks.push('string-replace:layoutconfig');

            grunt.task.run(tasks);

            themeConfig.current = theme;
            grunt.file.write('./config/theme.json', JSON.stringify(themeConfig));

            return true;
        }

        grunt.log.error('No such theme: ' + theme);
    });
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';

const cached = {};
function registerModel(app, model) {
  if (!cached[model.namespace]) {
    app.model(model);
    cached[model.namespace] = 1;
  }
}

function asyncComponent(config) {
  const { resolve } = config;

  return class DynamicComponent extends Component {
    constructor(...args) {
      super(...args);
      this.LoadingComponent =
        config.LoadingComponent || (() => null);
      this.state = {
        AsyncComponent: null,
      };
      this.load();
    }

    componentDidMount() {
      this.mounted = true;
    }

    load() {
      resolve().then((m) => {
        const AsyncComponent = m.default || m;
        if (this.mounted) {
          this.setState({ AsyncComponent });
        } else {
          this.state.AsyncComponent = AsyncComponent; // eslint-disable-line
        }
      });
    }

    render() {
      const { AsyncComponent } = this.state;
      const { LoadingComponent } = this;
      if (AsyncComponent) return <AsyncComponent {...this.props} />;

      return <LoadingComponent {...this.props} />;
    }
  };
}

export default function dynamic(config) {
  const { app, models: resolveModels, component: resolveComponent } = config;
  return asyncComponent({
    resolve: config.resolve || function () {
      const models = typeof resolveModels === 'function' ? resolveModels() : [];
      const component = resolveComponent();
      return new Promise((resolve) => {
        Promise.all([...models, component]).then((ret) => {
          if (!models || !models.length) {
            return resolve(ret[0]);
          } else {
            const len = models.length;
            ret.slice(0, len).forEach((m) => {
              registerModel(app, m);
            });
            resolve(ret[len]);
          }
        });
      });
    },
    ...config,
  });
}
<commit_msg>fix: check module.default when registerModel<commit_after>import React, { Component } from 'react';

const cached = {};
function registerModel(app, model) {
  if (!cached[model.namespace]) {
    app.model(model.default || model);
    cached[model.namespace] = 1;
  }
}

function asyncComponent(config) {
  const { resolve } = config;

  return class DynamicComponent extends Component {
    constructor(...args) {
      super(...args);
      this.LoadingComponent =
        config.LoadingComponent || (() => null);
      this.state = {
        AsyncComponent: null,
      };
      this.load();
    }

    componentDidMount() {
      this.mounted = true;
    }

    load() {
      resolve().then((m) => {
        const AsyncComponent = m.default || m;
        if (this.mounted) {
          this.setState({ AsyncComponent });
        } else {
          this.state.AsyncComponent = AsyncComponent; // eslint-disable-line
        }
      });
    }

    render() {
      const { AsyncComponent } = this.state;
      const { LoadingComponent } = this;
      if (AsyncComponent) return <AsyncComponent {...this.props} />;

      return <LoadingComponent {...this.props} />;
    }
  };
}

export default function dynamic(config) {
  const { app, models: resolveModels, component: resolveComponent } = config;
  return asyncComponent({
    resolve: config.resolve || function () {
      const models = typeof resolveModels === 'function' ? resolveModels() : [];
      const component = resolveComponent();
      return new Promise((resolve) => {
        Promise.all([...models, component]).then((ret) => {
          if (!models || !models.length) {
            return resolve(ret[0]);
          } else {
            const len = models.length;
            ret.slice(0, len).forEach((m) => {
              registerModel(app, m);
            });
            resolve(ret[len]);
          }
        });
      });
    },
    ...config,
  });
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 eBay Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';
function StringBuilder() {
    this.str = '';
}

StringBuilder.prototype = {
    write: function(str) {
        this.str += str;
        return this;
    },

    /**
     * Converts the string buffer into a String.
     *
     * @returns {String} The built String
     */
    toString: function() {
        return this.str;
    }
};

var EventEmitter = require('events').EventEmitter;

var includeStack = typeof process !== 'undefined' && process.env.NODE_ENV === 'development';

var voidWriter = {
    write: function() {}
};

function onProxy(asyncWriter, type, event, callback) {
    var attributes = asyncWriter.attributes;

    if (event === 'end') {
        if (attributes.ended) {
            callback();
            return asyncWriter;
        }
    }

    var events = attributes.events;
    events[type](event, callback);
    return asyncWriter;
}

function Fragment(asyncWriter) {
    this.asyncWriter = asyncWriter;
    // The asyncWriter that this async fragment is associated with
    this.writer = asyncWriter.writer;
    // The original writer this fragment was associated with
    this.finished = false;
    // Used to keep track if this async fragment was ended
    this.flushed = false;
    // Set to true when the contents of this async fragment have been
    // flushed to the original writer
    this.next = null;
    // A link to the next sibling async fragment (if any)
    this.ready = true;    // Will be set to true if this fragment is ready to be flushed
                          // (i.e. when there are no async fragments preceeding this fragment)
}
function flushNext(fragment, writer) {
    var next = fragment.next;
    if (next) {
        next.ready = true;
        // Since we have flushed the next fragment is ready
        next.writer = next.asyncWriter.writer = writer;
        // Update the next fragment to use the original writer
        next.flush();    // Now flush the next fragment (if it is not finish then it will just do nothing)
    }
}
function BufferedFragment(asyncWriter, buffer) {
    Fragment.call(this, asyncWriter);
    this.buffer = buffer;
}
BufferedFragment.prototype = {
    flush: function () {
        var writer = this.writer;
        writer.write(this.buffer.toString());
        this.flushed = true;
        flushNext(this, writer);
    }
};

function AsyncFragment(asyncWriter) {
    Fragment.call(this, asyncWriter);
}

AsyncFragment.prototype = {
    end: function () {
        if (!this.finished) {
            // Make sure end is only called once by the user
            this.finished = true;

            if (this.ready) {
                // There are no nested asynchronous fragments that are
                // remaining and we are ready to be flushed then let's do it!
                this.flush();
            }
        }
    },
    flush: function () {
        if (!this.finished) {
            // Skipped Flushing since not finished
            return;
        }
        this.flushed = true;
        var writer = this.writer;
        this.writer = this.asyncWriter.writer = voidWriter; // Prevent additional out-of-order writes
        flushNext(this, writer);
    }
};

function AsyncWriter(writer, attributes) {
    this.attributes = attributes || (attributes = {});
    this._af = this._prevAF = this._parentAF = null;
    this._isSync = false;

    if (!attributes.events) {
        attributes.events = new EventEmitter();
    }

    if (!attributes.async) {
        if (writer && writer.end) {
            this.on('end', function() {
                writer.end();
            });
        }

        attributes.async = {
            remaining: 0,
            ended: false,
            last: 0,
            lastFlushSupported: this.lastFlushSupported !== false
        };
    }

    if (!writer) {
        writer = new StringBuilder();
    }

    this.writer = this.stream = writer;
}

AsyncWriter.DEFAULT_TIMEOUT = 10000;

AsyncWriter.prototype = {
    constructor: AsyncWriter,

    isAsyncWriter: AsyncWriter,

    sync: function() {
        this._isSync = true;
    },
    getAttributes: function () {
        return this.attributes;
    },
    getAttribute: function (name) {
        return this.attributes[name];
    },
    write: function (str) {
        if (str != null) {
            this.writer.write(str.toString());
        }
        return this;
    },
    getOutput: function () {
        return this.writer.toString();
    },
    captureString: function (func, thisObj) {
        var sb = new StringBuilder();
        this.swapWriter(sb, func, thisObj);
        return sb.toString();
    },
    swapWriter: function (newWriter, func, thisObj) {
        var oldWriter = this.writer;
        try {
            this.writer = newWriter;
            func.call(thisObj);
        } finally {
            this.writer = oldWriter;
        }
    },
    createNestedContext: function (writer) {
        var _this = this;
        var child = new AsyncWriter(writer, _this.attributes);
        // Keep a reference to the original stream. This was done because when
        // rendering to a response stream we can get access to the request/response
        // to figure out the locale and other information associated with the
        // client. Without this we would have to rely on the request being
        // passed around everywhere or rely on something like continuation-local-storage
        // which has shown to be unreliable in some situations.
        child.stream = _this.stream;
        return child;
    },
    beginAsync: function (options) {
        if (this._isSync) {
            throw new Error('beginAsync() not allowed when using renderSync()');
        }
        // Keep a count of all of the async fragments for this rendering

        var ready = true;

        // Create a new asyncWriter that the async fragment can write to.
        // The new async asyncWriter will use the existing writer and
        // the writer for the current asyncWriter (which will continue to be used)
        // will be replaced with a string buffer writer
        var asyncContext = this.createNestedContext(this.writer);
        var buffer = this.writer = new StringBuilder();
        var asyncFragment = new AsyncFragment(asyncContext);
        var bufferedFragment = new BufferedFragment(this, buffer);
        asyncFragment.next = bufferedFragment;
        asyncContext._af = asyncFragment;
        asyncContext._parentAF = asyncFragment;
        var prevAsyncFragment = this._prevAF || this._parentAF;
        // See if we are being buffered by a previous asynchronous
        // fragment
        if (prevAsyncFragment) {
            // Splice in our two new fragments and add a link to the previous async fragment
            // so that it can let us know when we are ready to be flushed
            bufferedFragment.next = prevAsyncFragment.next;
            prevAsyncFragment.next = asyncFragment;
            if (!prevAsyncFragment.flushed) {
                ready = false;    // If we are preceeded by another async fragment then we aren't ready to be flushed
            }
        }
        asyncFragment.ready = ready;
        // Set the ready flag based on our earlier checks above
        this._prevAF = bufferedFragment;
        // Record the previous async fragment for linking purposes

        asyncContext.handleBeginAsync(options);

        return asyncContext;
    },

    handleBeginAsync: function(options) {
        var _this = this;

        var async = _this.attributes.async;

        var timeout;
        var name;

        async.remaining++;

        if (options != null) {
            if (typeof options === 'number') {
                timeout = options;
            } else {
                timeout = options.timeout;

                if (options.last === true) {
                    if (timeout == null) {
                        // Don't assign a timeout to last flush fragments
                        // unless it is explicitly given a timeout
                        timeout = 0;
                    }

                    async.last++;
                }

                name = options.name;
            }
        }

        if (timeout == null) {
            timeout = AsyncWriter.DEFAULT_TIMEOUT;
        }

        _this.stack = includeStack ? new Error().stack : null;
        _this.name = name;

        if (timeout > 0) {
            _this._timeoutId = setTimeout(function() {
                _this.error(new Error('Async fragment ' + (name ? '(' + name + ') ': '') + 'timed out after ' + timeout + 'ms'));
            }, timeout);
        }
    },
    on: function(event, callback) {
        return onProxy(this, 'on', event, callback);
    },

    once: function(event, callback) {
        return onProxy(this, 'once', event, callback);
    },

    emit: function(event) {
        var attributes = this.attributes;

        if (event === 'end') {
            attributes.ended = true;
        }

        var events = attributes.events;
        events.emit.apply(events, arguments);
        return this;
    },

    pipe: function(stream) {
        this.stream.pipe(stream);
        return this;
    },

    error: function(e) {
        try {
            var stack = this.stack;
            var name = this.name;
            e = new Error('Async fragment failed' + (name ? ' (' + name + ')': '') + '. Exception: ' + (e.stack || e) + (stack ? ('\nCreation stack trace: ' + stack) : ''));
            this.emit('error', e);
        } finally {
             this.end();
        }
    },

    end: function(data) {
        if (data) {
            this.write(data);
        }

        var asyncFragment = this._af;

        if (asyncFragment) {
            asyncFragment.end();
            this.handleEnd(true);
        } else {
            this.handleEnd(false);
        }

        return this;
    },

    handleEnd: function(isAsync) {

        var async = this.attributes.async;
        var isCompleted = false;

        // Keep track of how many asynchronous fragments are in the template
        // NOTE: firstPassComplete changes to true after processing all of the nodes of the template
        if (isAsync) {
            var timeoutId = this._timeoutId;
            if (timeoutId) {
                clearTimeout(timeoutId);
            }

            if (--async.remaining - async.last === 0 && async.ended) {
                isCompleted = true;
            }
        } else {
            async.ended = true;

            if (async.remaining - async.last === 0) {
                isCompleted = true;
            }
        }

        if (isCompleted) {
            if (!async.lastFired) {
                this.emit('last');
                async.last = 0;
                async.lastFired = true;
            }

            if (async.remaining === 0) {
                this.emit('end');
            }
        }
    }
};

AsyncWriter.prototype.w = AsyncWriter.prototype.write;

AsyncWriter.enableAsyncStackTrace = function() {
    includeStack = true;
};

module.exports = AsyncWriter;
<commit_msg>Renamed 'attributes' to 'global' (kept attributes for legacy reasons)<commit_after>/*
 * Copyright 2011 eBay Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';
function StringBuilder() {
    this.str = '';
}

StringBuilder.prototype = {
    write: function(str) {
        this.str += str;
        return this;
    },

    /**
     * Converts the string buffer into a String.
     *
     * @returns {String} The built String
     */
    toString: function() {
        return this.str;
    }
};

var EventEmitter = require('events').EventEmitter;

var includeStack = typeof process !== 'undefined' && process.env.NODE_ENV === 'development';

var voidWriter = {
    write: function() {}
};

function onProxy(asyncWriter, type, event, callback) {
    var global = asyncWriter.global;

    if (event === 'end') {
        if (global.ended) {
            callback();
            return asyncWriter;
        }
    }

    var events = global.events;
    events[type](event, callback);
    return asyncWriter;
}

function Fragment(asyncWriter) {
    this.asyncWriter = asyncWriter;
    // The asyncWriter that this async fragment is associated with
    this.writer = asyncWriter.writer;
    // The original writer this fragment was associated with
    this.finished = false;
    // Used to keep track if this async fragment was ended
    this.flushed = false;
    // Set to true when the contents of this async fragment have been
    // flushed to the original writer
    this.next = null;
    // A link to the next sibling async fragment (if any)
    this.ready = true;    // Will be set to true if this fragment is ready to be flushed
                          // (i.e. when there are no async fragments preceeding this fragment)
}
function flushNext(fragment, writer) {
    var next = fragment.next;
    if (next) {
        next.ready = true;
        // Since we have flushed the next fragment is ready
        next.writer = next.asyncWriter.writer = writer;
        // Update the next fragment to use the original writer
        next.flush();    // Now flush the next fragment (if it is not finish then it will just do nothing)
    }
}
function BufferedFragment(asyncWriter, buffer) {
    Fragment.call(this, asyncWriter);
    this.buffer = buffer;
}
BufferedFragment.prototype = {
    flush: function () {
        var writer = this.writer;
        writer.write(this.buffer.toString());
        this.flushed = true;
        flushNext(this, writer);
    }
};

function AsyncFragment(asyncWriter) {
    Fragment.call(this, asyncWriter);
}

AsyncFragment.prototype = {
    end: function () {
        if (!this.finished) {
            // Make sure end is only called once by the user
            this.finished = true;

            if (this.ready) {
                // There are no nested asynchronous fragments that are
                // remaining and we are ready to be flushed then let's do it!
                this.flush();
            }
        }
    },
    flush: function () {
        if (!this.finished) {
            // Skipped Flushing since not finished
            return;
        }
        this.flushed = true;
        var writer = this.writer;
        this.writer = this.asyncWriter.writer = voidWriter; // Prevent additional out-of-order writes
        flushNext(this, writer);
    }
};

function AsyncWriter(writer, global) {
    this.global = this.attributes /* legacy */ = global || (global = {});
    this._af = this._prevAF = this._parentAF = null;
    this._isSync = false;

    if (!global.events) {
        global.events = new EventEmitter();
    }

    if (!global.async) {
        if (writer && writer.end) {
            this.on('end', function() {
                writer.end();
            });
        }

        global.async = {
            remaining: 0,
            ended: false,
            last: 0,
            lastFlushSupported: this.lastFlushSupported !== false
        };
    }

    if (!writer) {
        writer = new StringBuilder();
    }

    this.writer = this.stream = writer;
}

AsyncWriter.DEFAULT_TIMEOUT = 10000;

AsyncWriter.prototype = {
    constructor: AsyncWriter,

    isAsyncWriter: AsyncWriter,

    sync: function() {
        this._isSync = true;
    },
    getAttributes: function () {
        return this.global;
    },
    getAttribute: function (name) {
        return this.global[name];
    },
    write: function (str) {
        if (str != null) {
            this.writer.write(str.toString());
        }
        return this;
    },
    getOutput: function () {
        return this.writer.toString();
    },
    captureString: function (func, thisObj) {
        var sb = new StringBuilder();
        this.swapWriter(sb, func, thisObj);
        return sb.toString();
    },
    swapWriter: function (newWriter, func, thisObj) {
        var oldWriter = this.writer;
        this.writer = newWriter;
        func.call(thisObj);
        this.writer = oldWriter;
    },
    createNestedContext: function (writer) {
        var _this = this;
        var child = new AsyncWriter(writer, _this.global);
        // Keep a reference to the original stream. This was done because when
        // rendering to a response stream we can get access to the request/response
        // to figure out the locale and other information associated with the
        // client. Without this we would have to rely on the request being
        // passed around everywhere or rely on something like continuation-local-storage
        // which has shown to be unreliable in some situations.
        child.stream = _this.stream;
        return child;
    },
    beginAsync: function (options) {
        if (this._isSync) {
            throw new Error('beginAsync() not allowed when using renderSync()');
        }
        // Keep a count of all of the async fragments for this rendering

        var ready = true;

        // Create a new asyncWriter that the async fragment can write to.
        // The new async asyncWriter will use the existing writer and
        // the writer for the current asyncWriter (which will continue to be used)
        // will be replaced with a string buffer writer
        var asyncContext = this.createNestedContext(this.writer);
        var buffer = this.writer = new StringBuilder();
        var asyncFragment = new AsyncFragment(asyncContext);
        var bufferedFragment = new BufferedFragment(this, buffer);
        asyncFragment.next = bufferedFragment;
        asyncContext._af = asyncFragment;
        asyncContext._parentAF = asyncFragment;
        var prevAsyncFragment = this._prevAF || this._parentAF;
        // See if we are being buffered by a previous asynchronous
        // fragment
        if (prevAsyncFragment) {
            // Splice in our two new fragments and add a link to the previous async fragment
            // so that it can let us know when we are ready to be flushed
            bufferedFragment.next = prevAsyncFragment.next;
            prevAsyncFragment.next = asyncFragment;
            if (!prevAsyncFragment.flushed) {
                ready = false;    // If we are preceeded by another async fragment then we aren't ready to be flushed
            }
        }
        asyncFragment.ready = ready;
        // Set the ready flag based on our earlier checks above
        this._prevAF = bufferedFragment;
        // Record the previous async fragment for linking purposes

        asyncContext.handleBeginAsync(options);

        return asyncContext;
    },

    handleBeginAsync: function(options) {
        var _this = this;

        var async = _this.global.async;

        var timeout;
        var name;

        async.remaining++;

        if (options != null) {
            if (typeof options === 'number') {
                timeout = options;
            } else {
                timeout = options.timeout;

                if (options.last === true) {
                    if (timeout == null) {
                        // Don't assign a timeout to last flush fragments
                        // unless it is explicitly given a timeout
                        timeout = 0;
                    }

                    async.last++;
                }

                name = options.name;
            }
        }

        if (timeout == null) {
            timeout = AsyncWriter.DEFAULT_TIMEOUT;
        }

        _this.stack = includeStack ? new Error().stack : null;
        _this.name = name;

        if (timeout > 0) {
            _this._timeoutId = setTimeout(function() {
                _this.error(new Error('Async fragment ' + (name ? '(' + name + ') ': '') + 'timed out after ' + timeout + 'ms'));
            }, timeout);
        }
    },
    on: function(event, callback) {
        return onProxy(this, 'on', event, callback);
    },

    once: function(event, callback) {
        return onProxy(this, 'once', event, callback);
    },

    emit: function(event) {
        var global = this.global;

        if (event === 'end') {
            global.ended = true;
        }

        var events = global.events;
        events.emit.apply(events, arguments);
        return this;
    },

    pipe: function(stream) {
        this.stream.pipe(stream);
        return this;
    },

    error: function(e) {
        try {
            var stack = this.stack;
            var name = this.name;
            e = new Error('Async fragment failed' + (name ? ' (' + name + ')': '') + '. Exception: ' + (e.stack || e) + (stack ? ('\nCreation stack trace: ' + stack) : ''));
            this.emit('error', e);
        } finally {
             this.end();
        }
    },

    end: function(data) {
        if (data) {
            this.write(data);
        }

        var asyncFragment = this._af;

        if (asyncFragment) {
            asyncFragment.end();
            this.handleEnd(true);
        } else {
            this.handleEnd(false);
        }

        return this;
    },

    handleEnd: function(isAsync) {

        var async = this.global.async;
        var isCompleted = false;

        // Keep track of how many asynchronous fragments are in the template
        // NOTE: firstPassComplete changes to true after processing all of the nodes of the template
        if (isAsync) {
            var timeoutId = this._timeoutId;
            if (timeoutId) {
                clearTimeout(timeoutId);
            }

            if (--async.remaining - async.last === 0 && async.ended) {
                isCompleted = true;
            }
        } else {
            async.ended = true;

            if (async.remaining - async.last === 0) {
                isCompleted = true;
            }
        }

        if (isCompleted) {
            if (!async.lastFired) {
                this.emit('last');
                async.last = 0;
                async.lastFired = true;
            }

            if (async.remaining === 0) {
                this.emit('end');
            }
        }
    }
};

AsyncWriter.prototype.w = AsyncWriter.prototype.write;

AsyncWriter.enableAsyncStackTrace = function() {
    includeStack = true;
};

module.exports = AsyncWriter;
<|endoftext|>


<commit_before>function update_dashboard_metadata(dashboard) {
  var dash = dashboard.toJSON()
  delete dash.definition
  ds.manager.update(dash)
}
/*
 * Logic for the dashboard-toolbar.html template.
 */

ds.app.add_mode_handler('edit', {
  enter: function() {
    $(".ds-dashboard-info-edit-panel").html(ds.templates.edit.dashboard_panel(ds.manager.current.dashboard));
    $('#ds-edit-info-button').addClass('active')

      $.fn.editable.defaults.mode = 'inline'

      /** Title */
      $("#ds-info-panel-edit-title").editable({
        unsavedclass: null,
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.title = newValue
          update_dashboard_metadata(ds.manager.current.dashboard)
        }
      })

      /** Category */
      $("#ds-info-panel-edit-category").editable({
        unsavedclass: null,
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.category = newValue
          update_dashboard_metadata(ds.manager.current.dashboard)
        }
      })

      $("#ds-info-panel-edit-summary").editable({
        unsavedclass: null,
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.summary = newValue
          update_dashboard_metadata(ds.manager.current.dashboard)
        }
      })

      $("#ds-info-panel-edit-description").editable({
        unsavedclass: null,
        value: ds.manager.current.dashboard.description || '',
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.description = newValue
          update_dashboard_metadata(ds.manager.current.dashboard)
        },
        display: function(value, response) {
          $(this).html(marked(value))
        }
      })

      var tags = ds.manager.current.dashboard.tags || []
      $("#ds-info-panel-edit-tags").tagsManager({
        hiddenTagListName: 'ds-info-panel-edit-taglist',
        tagClass: 'badge badge-primary',
        prefilled: tags.map(function(tag) {
                     return tag.name
                   })
      })
  },
  exit: function() {
    $('#ds-edit-info-button').removeClass('active')
  }
})

$(document).ready(function() {

  /**
   * Handlers for the Info Edit panel.
   */
  $(document).on('click', '#ds-edit-info-button', function(e) {
    ds.app.toggle_mode(ds.app.Mode.EDIT)
  })

  /**
   * Handler for tag changes. This gets run each time a complete tag
   * is added or removed.
   */
  $(document).on('change', '[name="ds-info-panel-edit-taglist"]', function(e) {
    var tags = $('#ds-info-panel-edit-tags').tagsManager('tags');
    ds.manager.current.dashboard.set_tags(tags);
    update_dashboard_metadata(ds.manager.current.dashboard)
  })

  $(document).on('click', '#ds-toggle-interactive-button', function(e) {
    if (ds.manager.toggle_interactive_charts()) {
      $('#ds-toggle-interactive-button').removeClass('active')
    } else {
      $('#ds-toggle-interactive-button').addClass('active')
    }
  })

  $(document).on('click', '#ds-enter-fullscreen-button', function(e) {
    ds.app.switch_to_mode(ds.app.Mode.DISPLAY)
  })

  $(document).on('click', '#ds-exit-display-mode-button', function(e) {
    ds.app.switch_to_mode(ds.app.Mode.STANDARD)
  })

  $(document).on('click', '#ds-delete-dashboard-button', function(e) {
    ds.manager.delete_current()
  })

  $(document).on('click', '#ds-save-dashboard-button', function(e) {
    ds.manager.update_definition(ds.manager.current.dashboard, function() {
      ds.manager.success('Dashboard saved')
    })
  })

  $(document).on('click', '#ds-new-section-button', function(e) {
    var dash = ds.manager.current.dashboard
    dash.definition.add(ds.models.section())
    dash.update_index()
    ds.manager.update_item_view(dash.definition)
  })

  $(document).on('click', '#ds-view-dashboard-source-button', function(e) {
    var dashboard = ds.manager.current.dashboard;
    $.get(dashboard.href + '?definition=true', function(data) {
      var contents = '
' + ds.templates.edit.item_source({item:data.dashboards[0]}) + '
'
      $(ds.manager.current.element).html(contents)
    })
  })

})
<commit_msg>update_dashboard_metadata was unnecessary<commit_after>/*
 * Logic for the dashboard-toolbar.html template.
 */

ds.app.add_mode_handler('edit', {
  enter: function() {
    $(".ds-dashboard-info-edit-panel").html(ds.templates.edit.dashboard_panel(ds.manager.current.dashboard));
    $('#ds-edit-info-button').addClass('active')

      $.fn.editable.defaults.mode = 'inline'

      /** Title */
      $("#ds-info-panel-edit-title").editable({
        unsavedclass: null,
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.title = newValue
          ds.manager.update(ds.manager.current.dashboard)
        }
      })

      /** Category */
      $("#ds-info-panel-edit-category").editable({
        unsavedclass: null,
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.category = newValue
          ds.manager.update(ds.manager.current.dashboard)
        }
      })

      $("#ds-info-panel-edit-summary").editable({
        unsavedclass: null,
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.summary = newValue
          ds.manager.update(ds.manager.current.dashboard)
        }
      })

      $("#ds-info-panel-edit-description").editable({
        unsavedclass: null,
        value: ds.manager.current.dashboard.description || '',
        success: function(ignore, newValue) {
          ds.manager.current.dashboard.description = newValue
          ds.manager.update(ds.manager.current.dashboard)
        },
        display: function(value, response) {
          $(this).html(marked(value))
        }
      })

      var tags = ds.manager.current.dashboard.tags || []
      $("#ds-info-panel-edit-tags").tagsManager({
        hiddenTagListName: 'ds-info-panel-edit-taglist',
        tagClass: 'badge badge-primary',
        prefilled: tags.map(function(tag) {
                     return tag.name
                   })
      })
  },
  exit: function() {
    $('#ds-edit-info-button').removeClass('active')
  }
})

$(document).ready(function() {

  /**
   * Handlers for the Info Edit panel.
   */
  $(document).on('click', '#ds-edit-info-button', function(e) {
    ds.app.toggle_mode(ds.app.Mode.EDIT)
  })

  /**
   * Handler for tag changes. This gets run each time a complete tag
   * is added or removed.
   */
  $(document).on('change', '[name="ds-info-panel-edit-taglist"]', function(e) {
    var tags = $('#ds-info-panel-edit-tags').tagsManager('tags');
    ds.manager.current.dashboard.set_tags(tags);
    ds.manager.update(ds.manager.current.dashboard)
  })

  $(document).on('click', '#ds-toggle-interactive-button', function(e) {
    if (ds.manager.toggle_interactive_charts()) {
      $('#ds-toggle-interactive-button').removeClass('active')
    } else {
      $('#ds-toggle-interactive-button').addClass('active')
    }
  })

  $(document).on('click', '#ds-enter-fullscreen-button', function(e) {
    ds.app.switch_to_mode(ds.app.Mode.DISPLAY)
  })

  $(document).on('click', '#ds-exit-display-mode-button', function(e) {
    ds.app.switch_to_mode(ds.app.Mode.STANDARD)
  })

  $(document).on('click', '#ds-delete-dashboard-button', function(e) {
    ds.manager.delete_current()
  })

  $(document).on('click', '#ds-save-dashboard-button', function(e) {
    ds.manager.update_definition(ds.manager.current.dashboard, function() {
      ds.manager.success('Dashboard saved')
    })
  })

  $(document).on('click', '#ds-new-section-button', function(e) {
    var dash = ds.manager.current.dashboard
    dash.definition.add(ds.models.section())
    dash.update_index()
    ds.manager.update_item_view(dash.definition)
  })

  $(document).on('click', '#ds-view-dashboard-source-button', function(e) {
    var dashboard = ds.manager.current.dashboard;
    $.get(dashboard.href + '?definition=true', function(data) {
      var contents = '
' + ds.templates.edit.item_source({item:data.dashboards[0]}) + '
'
      $(ds.manager.current.element).html(contents)
    })
  })

})
<|endoftext|>


<commit_before>import * as React from 'react';
import * as csp   from 'plexus-csp';

import * as delaney  from '../dsymbols/delaney';
import Display3d from './Display3d';
import makeScene from './makeScene';

const tilings = {
  dia: '<1.1:2 3:2,1 2,1 2,2:6,3 2,6>',
  pcu: '<1.1:1 3:1,1,1,1:4,3,4>'
};

const App = React.createClass({
  displayName: 'App',

  getInitialState() {
    return {};
  },

  handleResize(data) {
    this.setState({
      width: window.innerWidth,
      height: window.innerHeight
    });
  },

  componentDidMount() {
    const setState = this.setState.bind(this);

    this.handleResize();
    window.addEventListener('resize', this.handleResize);

    csp.go(function*() {
      try {
        const scene = yield makeScene(delaney.parse(tilings.dia));
        const camera = scene.getObjectByName('camera');
        const cameraParameters = { distance: camera.position.z };

        setState({ scene, camera, cameraParameters });
      } catch(ex) { console.error(ex); }
    });
  },

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  },

  render() {
    if (this.state.scene == null)
      return React.DOM.div();

    return React.DOM.div(
      null,
      React.createElement(Display3d, {
        scene           : this.state.scene,
        camera          : this.state.camera,
        cameraParameters: this.state.cameraParameters,
        width           : this.state.width - 20,
        height          : this.state.height - 20
      }));
  }
});

React.render(React.createElement(App), document.getElementById('react-main'));
<commit_msg>add a test paragraph on top of the 3d display<commit_after>import * as React from 'react';
import * as csp   from 'plexus-csp';

import * as delaney  from '../dsymbols/delaney';
import Display3d from './Display3d';
import makeScene from './makeScene';

const tilings = {
  dia: '<1.1:2 3:2,1 2,1 2,2:6,3 2,6>',
  pcu: '<1.1:1 3:1,1,1,1:4,3,4>'
};

const App = React.createClass({
  displayName: 'App',

  getInitialState() {
    return {};
  },

  handleResize(data) {
    this.setState({
      width: window.innerWidth,
      height: window.innerHeight
    });
  },

  componentDidMount() {
    const setState = this.setState.bind(this);

    this.handleResize();
    window.addEventListener('resize', this.handleResize);

    csp.go(function*() {
      try {
        const scene = yield makeScene(delaney.parse(tilings.dia));
        const camera = scene.getObjectByName('camera');
        const cameraParameters = { distance: camera.position.z };

        setState({ scene, camera, cameraParameters });
      } catch(ex) { console.error(ex); }
    });
  },

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  },

  render3d() {
    if (this.state.scene != null)
      return React.createElement(Display3d, {
        scene           : this.state.scene,
        camera          : this.state.camera,
        cameraParameters: this.state.cameraParameters,
        width           : this.state.width - 20,
        height          : this.state.height - 20
      });
  },

  render() {
    return React.DOM.div(
      null,
      this.render3d(),
      React.DOM.p(
        {
          style: {
            zIndex    : 10,
            position  : 'fixed',
            top       : '50px',
            left      : '50px',
            background: 'lightyellow',
            border    : '1px solid lightgray',
            padding   : '5px'
          }
        },
        "Hello Gavrog!"
      ));
  }
});

React.render(React.createElement(App), document.getElementById('react-main'));
<|endoftext|>


<commit_before>//  ==========================================================================
//  Project:   MySystem
//  Copyright: ©2011 Concord Consortium
//  ==========================================================================

/*globals MySystem alert*/

/**
 @class MySystem.rulController
  Description: orchestrates rule evaluation, with rules, nodes, and custom expressions.
  @extends SC.ObjectController
*/
MySystem.rulesController = SC.ObjectController.create({

  success     : false,
  feedback    : "(empty feedback)",
  suggestions : [],

  addSuggestion: function(suggestion) {
    this.suggestions.push(suggestion);
  },

  addRuleSuggestion: function(rule_select) {
    var rule = this.find(rule_select);
    this.addSuggestion(rule.get('suggestion'));
  },

  rules: function() {
    var rules = MySystem.activityController.get('diagramRules');
    return rules;
  },

  find: function(exampleRule) {
    var rules = this.rules().toArray(),
    rule      = null,
    found     = null,
    i         = 0;

    // assume that this a real rule
    if (typeof exampleRule === "object") {
      found = exampleRule;
    }

    // search by number
    if (typeof exampleRule === "number") {
      found = rules[exampleRule];
    }

    // search by name
    if (typeof exampleRule === "string") {
      for(i=0; i< rules.length; i++) {
        rule = rules[i];
        if (rule.get("name") === exampleRule) {
          found = rule;
        }
      }
    }

    // TODO: report something to the console, or to the user or something:
    if (null === found) {
      this.addSuggestion("can't find rule named " + exampleRule);
    }
    return found;
  },

  // return the eval result of the
  check: function(_rule) {
    var rule = this.find(_rule);
    var nodes = MySystem.store.find(MySystem.Node);
    var Rules = this; // TODO: pull out rule helpers to module
    return rule.check(nodes,Rules);
  },

  // run one rule, adding suggestion if
  run: function(_rule) {
    var rule = this.find(_rule);
    var self = this;
    if (!this.check(rule,self)) {
      this.addSuggestion(rule.get('suggestion'));
    }
  },

  runAll: function() {
    var rules = this.rules(),
    self      = this;

    rules.forEach( function (rule) {
      self.run(rule);
    });
  },

  // runDiagramRules: runs the diagram rules
  // updates "success" and "feedback" properties
  runDiagramRules: function() {

    var rules                 = this.rules(),
    enableCustomRuleEvaluator = MySystem.activityController.get('enableCustomRuleEvaluator'),
    feedbackRules             = MySystem.activityController.get('feedbackRules'),
    correctFeedback           = MySystem.activityController.get('correctFeedback'),
    success                   = this.get('success'),
    feedback                  = this.get('feedback');

    // clear out previous data:
    var suggestions = this.suggestions = [];

    // it would be nice if there was a nodes(only) controller:
    var nodes = this.nodes = MySystem.store.find(MySystem.Node);

    if (typeof feedbackRules === 'string' && feedbackRules.length > 0) {
      this.evaluateFeedbackRules(feedbackRules);
    }

    this._trimFeedback();

    success  = (this.suggestions.get('length') === 0);
    feedback = success ? correctFeedback : this.suggestions.join(" \n");

    this.set('success', success);
    this.set('feedback', feedback);
  },

  _trimFeedback: function(){
    var maxFeedback = MySystem.activityController.get('maxFeedbackItems');
    if (maxFeedback && maxFeedback > 0 && this.suggestions.length > maxFeedback) {
      this.suggestions = this.suggestions.slice(0,maxFeedback);
    }
  },

  // true if the diagram has transformations
  // transformations are any nodes which output
  // energytypes other than their input... (berk_req.)
  hasTransformation: function() {
    var nodes = MySystem.store.find(MySystem.Node);

    // returns uuids for energytypes or 'unidenitfied_type'
    var linkTypes = function(node,linkTypes) {
      var links = node.get(linkTypes);
      return links.map( function (link) {
        return link.get('energyType') || 'unidenitfied_type';
        });
    };

    var hasTransform = function (node) {
      var inLinks = linkTypes(node,'inLinks').toArray();
      var outLinks = linkTypes(node,'outLinks').toArray();

      // we must have in and outlinks to transform
      if (inLinks.length < 1) { return false; }
      if (outLinks.length < 1) { return false; }

      // search for an outlink not in inlinks.
      for (var i = outLinks.length - 1; i >= 0; i--) {
        if (inLinks.indexOf(outLinks[i]) < 0) { return true; }
      }
      return false;
    };
    return (nodes.filter(hasTransform).length > 1);
  },

  // true if the icons were only used at most once.
  iconsUsedOnce: function() {
    var nodes = MySystem.store.find(MySystem.Node).toArray();
    var types = {};
    var i = 0;
    var duplicates = false;
    for(i = 0; i < nodes.length; i++) {
      var node = nodes[i];
      var nodeType = node.get('nodeType');
      if (typeof types[nodeType] === 'undefined') {
        types[nodeType] = 0;
      }
      else {
        types[nodeType] = types[nodeType] + 1;
        duplicates = true;
      }
    }
    return (!duplicates);
  },

  // true if all icons were used at least once.
  allIconsUsed: function() {
    var paeltteItems = MySystem.activityController.get('paletteItems');
    var nodes = MySystem.store.find(MySystem.Node);
    var found = paeltteItems.filter(function(paletteItem) {
      var found = nodes.findProperty("nodeType", paletteItem.get('uuid'));
      return (found !== null);
    });
    return (found.get('length') === paeltteItems.get('length') );
  },

  // true if there were links not defined in rules.
  extraLinks: function(rule_names) {
    // Look for links that don't match one of the 'should' link rules
    var links          = MySystem.store.find(MySystem.Link);
    var notAllowedLink = null;
    var rules          = MySystem.activityController.get('diagramRules');

    if (rule_names !== null && typeof rule_names !== 'undefined' && rule_names.length > 0) {
      rules = rules.filter( function(rule) {
        return (rule_names.indexOf(rule.get('name')) > -1);
      });
    }

    links = links.filter(function (link) {return link.isComplete();});
    notAllowedLink = links.find(function (link) {
      var positiveLinkRules = rules.filterProperty('hasLink').filter(function(rule){return !rule.get('not');});
      var matchingRule = positiveLinkRules.find(function (rule) {
        // need to handle the link check here, in the future this should be moved into the core code
        var paletteItem = rule.paletteItem(rule.get('type')),
            otherPaletteItem = rule.paletteItem(rule.get('otherNodeType'));

        switch(rule.get('linkDirection')) {
          case '-->':
            return rule.checkLink(link, paletteItem, otherPaletteItem);
          case '<--':
            return rule.checkLink(link, otherPaletteItem, paletteItem);
          case '---':
            return rule.checkLink(link, paletteItem, otherPaletteItem) || rule.checkLink(link, otherPaletteItem, paletteItem);
          default:
            throw "Invalid linkDirection value for diagram rule.";
        }
      });
      if(!matchingRule){ return YES; }
    });

    return (notAllowedLink !== null && notAllowedLink !== 'undefined');
  },

  hasNode: function(nodeName) {
    var nodes = MySystem.store.find(MySystem.Node);
    return (nodes.findProperty('nodeType',nodeName));
  },

  evaluateFeedbackRules: function(expression) {
    var self         = this,
        gaveFeedback = false,
        categories   = MySystem.activityController.get('rubricCategories'),
        nodes        = MySystem.store.find(MySystem.Node),
        rules        = MySystem.activityController.get('diagramRules'),

        ruleResults = {},

        resultsOfCategories = categories.forEach(function(c) {
          var name  = c.get('name'),
              value = false,
              found = null,
              rulesInCategory = rules.filterProperty('category',name);

          found = rulesInCategory.find(function(r) {
            if (r.check(nodes, MySystem.rulesController) === true) {
              return true;
            }
          });
          if (found) {
            value = true;
          }
          ruleResults[name] = value;
        }),

        // depricate me.
        addSuggestion = function(suggestion) {
          self.suggestions.push(suggestion);
        },

        feedback =  function(suggestion) {
          if(!gaveFeedback) {
            self.suggestions.push(suggestion);
            gaveFeedback = true;
          }
        },

        rule = function(ruleName) {
          return self.check.call(self,ruleName);
        },

        hasTransformation = function() {
          return self.hasTransformation.call(self);
        },

        iconsUsedOnce = function() {
          return self.iconsUsedOnce.call(self);
        },

        extraLinks = function() {
          return self.extraLinks.call(self);
        },

        allIconsUsed = function() {
          return self.allIconsUsed.call(self);
        },

        category = function(categoryName) {
          return ruleResults[categoryName] || false;
        },
        categoryExists = function(name) {
          return (typeof ruleResults[name] === 'undefined') ? false : true;
        },

        valueFromArgument = function(argument) {
          if (typeof argument === 'string')   {
            return categoryExists(argument) ? category(argument) : rule(argument);
          }
          if (typeof argument === 'function') { return argument.apply(self); }
          if (typeof argument === 'object')   { return argument.apply(self); }
          return argument; // hopefully a boolean
        },

        any = function() {
          var args = [].slice.apply(arguments);
          return args.reduce(function(a,b) {
             a = valueFromArgument(a);
             b = valueFromArgument(b);
            return (a||b);
          }, false);
        },

        all = function() {
          var args = [].slice.apply(arguments);
          return args.reduce(function(a,b) {
             a = valueFromArgument(a);
             b = valueFromArgument(b);
            return (a&&b);
          }, true);
        },

        not_any = function() {
          return (! any.apply(self,arguments));
        },
        none = not_any,

        not_all = function() {
          return (! all.apply(self,arguments));
        },

        makeFeedbackFunction = function(func) {
          return function() {
            var args = Array.prototype.slice.call(arguments,0,-1);
            var message = Array.prototype.slice.call(arguments,-1);
            var results = func.apply(self, args);
            if (results) {
              feedback(message);
            }
          };
        },

        all_f     = makeFeedbackFunction(all),
        any_f     = makeFeedbackFunction(any),
        not_any_f = makeFeedbackFunction(not_any),
        none_f    = makeFeedbackFunction(none),
        not_all_f = makeFeedbackFunction(not_all),

        errorMsg = "Feedback evaluation Error: \n%@";

    // this is the point of entry for evaluateFeedbackRules
    (function(){
      try {
        //var script = CoffeeScript.compile(expression,{thing: 10});
        eval(expression);
      }
      catch(e) {
        errorMsg = errorMsg.fmt(e);
        if (console && typeof console.log === 'function') {
          console.log(errorMsg);
        }
        alert(errorMsg);
      }
    }).call(self);

  }
});

<commit_msg>RulesController : properly bug fix hasTransformations() pre-canned rule.<commit_after>//  ==========================================================================
//  Project:   MySystem
//  Copyright: ©2011 Concord Consortium
//  ==========================================================================

/*globals MySystem alert*/

/**
 @class MySystem.rulController
  Description: orchestrates rule evaluation, with rules, nodes, and custom expressions.
  @extends SC.ObjectController
*/
MySystem.rulesController = SC.ObjectController.create({

  success     : false,
  feedback    : "(empty feedback)",
  suggestions : [],

  addSuggestion: function(suggestion) {
    this.suggestions.push(suggestion);
  },

  addRuleSuggestion: function(rule_select) {
    var rule = this.find(rule_select);
    this.addSuggestion(rule.get('suggestion'));
  },

  rules: function() {
    var rules = MySystem.activityController.get('diagramRules');
    return rules;
  },

  find: function(exampleRule) {
    var rules = this.rules().toArray(),
    rule      = null,
    found     = null,
    i         = 0;

    // assume that this a real rule
    if (typeof exampleRule === "object") {
      found = exampleRule;
    }

    // search by number
    if (typeof exampleRule === "number") {
      found = rules[exampleRule];
    }

    // search by name
    if (typeof exampleRule === "string") {
      for(i=0; i< rules.length; i++) {
        rule = rules[i];
        if (rule.get("name") === exampleRule) {
          found = rule;
        }
      }
    }

    // TODO: report something to the console, or to the user or something:
    if (null === found) {
      this.addSuggestion("can't find rule named " + exampleRule);
    }
    return found;
  },

  // return the eval result of the
  check: function(_rule) {
    var rule = this.find(_rule);
    var nodes = MySystem.store.find(MySystem.Node);
    var Rules = this; // TODO: pull out rule helpers to module
    return rule.check(nodes,Rules);
  },

  // run one rule, adding suggestion if
  run: function(_rule) {
    var rule = this.find(_rule);
    var self = this;
    if (!this.check(rule,self)) {
      this.addSuggestion(rule.get('suggestion'));
    }
  },

  runAll: function() {
    var rules = this.rules(),
    self      = this;

    rules.forEach( function (rule) {
      self.run(rule);
    });
  },

  // runDiagramRules: runs the diagram rules
  // updates "success" and "feedback" properties
  runDiagramRules: function() {

    var rules                 = this.rules(),
    enableCustomRuleEvaluator = MySystem.activityController.get('enableCustomRuleEvaluator'),
    feedbackRules             = MySystem.activityController.get('feedbackRules'),
    correctFeedback           = MySystem.activityController.get('correctFeedback'),
    success                   = this.get('success'),
    feedback                  = this.get('feedback');

    // clear out previous data:
    var suggestions = this.suggestions = [];

    // it would be nice if there was a nodes(only) controller:
    var nodes = this.nodes = MySystem.store.find(MySystem.Node);

    if (typeof feedbackRules === 'string' && feedbackRules.length > 0) {
      this.evaluateFeedbackRules(feedbackRules);
    }

    this._trimFeedback();

    success  = (this.suggestions.get('length') === 0);
    feedback = success ? correctFeedback : this.suggestions.join(" \n");

    this.set('success', success);
    this.set('feedback', feedback);
  },

  _trimFeedback: function(){
    var maxFeedback = MySystem.activityController.get('maxFeedbackItems');
    if (maxFeedback && maxFeedback > 0 && this.suggestions.length > maxFeedback) {
      this.suggestions = this.suggestions.slice(0,maxFeedback);
    }
  },

  // true if the diagram has transformations
  // transformations are any nodes which output
  // energytypes other than their input... (berk_req.)
  hasTransformation: function() {
    var nodes = MySystem.store.find(MySystem.Node);

    // returns uuids for energytypes or 'unidenitfied_type'
    var linkTypes = function(node,linkTypes) {
      var links = node.get(linkTypes);
      return links.map( function (link) {
        return link.get('energyType') || 'unidenitfied_type';
        });
    };

    var hasTransform = function (node) {
      var inLinks = linkTypes(node,'inLinks').toArray();
      var outLinks = linkTypes(node,'outLinks').toArray();

      // we must have in and outlinks to transform
      if (inLinks.length < 1) { return false; }
      if (outLinks.length < 1) { return false; }

      // search for an outlink not in inlinks.
      for (var i = outLinks.length - 1; i >= 0; i--) {
        if (inLinks.indexOf(outLinks[i]) < 0) { return true; }
      }
      return false;
    };
    var filtered = nodes.filter(hasTransform);
    return (filtered.get('length') >= 1);
  },

  // true if the icons were only used at most once.
  iconsUsedOnce: function() {
    var nodes = MySystem.store.find(MySystem.Node).toArray();
    var types = {};
    var i = 0;
    var duplicates = false;
    for(i = 0; i < nodes.length; i++) {
      var node = nodes[i];
      var nodeType = node.get('nodeType');
      if (typeof types[nodeType] === 'undefined') {
        types[nodeType] = 0;
      }
      else {
        types[nodeType] = types[nodeType] + 1;
        duplicates = true;
      }
    }
    return (!duplicates);
  },

  // true if all icons were used at least once.
  allIconsUsed: function() {
    var paeltteItems = MySystem.activityController.get('paletteItems');
    var nodes = MySystem.store.find(MySystem.Node);
    var found = paeltteItems.filter(function(paletteItem) {
      var found = nodes.findProperty("nodeType", paletteItem.get('uuid'));
      return (found !== null);
    });
    return (found.get('length') === paeltteItems.get('length') );
  },

  // true if there were links not defined in rules.
  extraLinks: function(rule_names) {
    // Look for links that don't match one of the 'should' link rules
    var links          = MySystem.store.find(MySystem.Link);
    var notAllowedLink = null;
    var rules          = MySystem.activityController.get('diagramRules');

    if (rule_names !== null && typeof rule_names !== 'undefined' && rule_names.length > 0) {
      rules = rules.filter( function(rule) {
        return (rule_names.indexOf(rule.get('name')) > -1);
      });
    }

    links = links.filter(function (link) {return link.isComplete();});
    notAllowedLink = links.find(function (link) {
      var positiveLinkRules = rules.filterProperty('hasLink').filter(function(rule){return !rule.get('not');});
      var matchingRule = positiveLinkRules.find(function (rule) {
        // need to handle the link check here, in the future this should be moved into the core code
        var paletteItem = rule.paletteItem(rule.get('type')),
            otherPaletteItem = rule.paletteItem(rule.get('otherNodeType'));

        switch(rule.get('linkDirection')) {
          case '-->':
            return rule.checkLink(link, paletteItem, otherPaletteItem);
          case '<--':
            return rule.checkLink(link, otherPaletteItem, paletteItem);
          case '---':
            return rule.checkLink(link, paletteItem, otherPaletteItem) || rule.checkLink(link, otherPaletteItem, paletteItem);
          default:
            throw "Invalid linkDirection value for diagram rule.";
        }
      });
      if(!matchingRule){ return YES; }
    });

    return (notAllowedLink !== null && notAllowedLink !== 'undefined');
  },

  hasNode: function(nodeName) {
    var nodes = MySystem.store.find(MySystem.Node);
    return (nodes.findProperty('nodeType',nodeName));
  },

  evaluateFeedbackRules: function(expression) {
    var self         = this,
        gaveFeedback = false,
        categories   = MySystem.activityController.get('rubricCategories'),
        nodes        = MySystem.store.find(MySystem.Node),
        rules        = MySystem.activityController.get('diagramRules'),

        ruleResults = {},

        resultsOfCategories = categories.forEach(function(c) {
          var name  = c.get('name'),
              value = false,
              found = null,
              rulesInCategory = rules.filterProperty('category',name);

          found = rulesInCategory.find(function(r) {
            if (r.check(nodes, MySystem.rulesController) === true) {
              return true;
            }
          });
          if (found) {
            value = true;
          }
          ruleResults[name] = value;
        }),

        // depricate me.
        addSuggestion = function(suggestion) {
          self.suggestions.push(suggestion);
        },

        feedback =  function(suggestion) {
          if(!gaveFeedback) {
            self.suggestions.push(suggestion);
            gaveFeedback = true;
          }
        },

        rule = function(ruleName) {
          return self.check.call(self,ruleName);
        },

        hasTransformation = function() {
          return self.hasTransformation.call(self);
        },

        iconsUsedOnce = function() {
          return self.iconsUsedOnce.call(self);
        },

        extraLinks = function() {
          return self.extraLinks.call(self);
        },

        allIconsUsed = function() {
          return self.allIconsUsed.call(self);
        },

        category = function(categoryName) {
          return ruleResults[categoryName] || false;
        },
        categoryExists = function(name) {
          return (typeof ruleResults[name] === 'undefined') ? false : true;
        },

        valueFromArgument = function(argument) {
          if (typeof argument === 'string')   {
            return categoryExists(argument) ? category(argument) : rule(argument);
          }
          if (typeof argument === 'function') { return argument.apply(self); }
          if (typeof argument === 'object')   { return argument.apply(self); }
          return argument; // hopefully a boolean
        },

        any = function() {
          var args = [].slice.apply(arguments);
          return args.reduce(function(a,b) {
             a = valueFromArgument(a);
             b = valueFromArgument(b);
            return (a||b);
          }, false);
        },

        all = function() {
          var args = [].slice.apply(arguments);
          return args.reduce(function(a,b) {
             a = valueFromArgument(a);
             b = valueFromArgument(b);
            return (a&&b);
          }, true);
        },

        not_any = function() {
          return (! any.apply(self,arguments));
        },
        none = not_any,

        not_all = function() {
          return (! all.apply(self,arguments));
        },

        makeFeedbackFunction = function(func) {
          return function() {
            var args = Array.prototype.slice.call(arguments,0,-1);
            var message = Array.prototype.slice.call(arguments,-1);
            var results = func.apply(self, args);
            if (results) {
              feedback(message);
            }
          };
        },

        all_f     = makeFeedbackFunction(all),
        any_f     = makeFeedbackFunction(any),
        not_any_f = makeFeedbackFunction(not_any),
        none_f    = makeFeedbackFunction(none),
        not_all_f = makeFeedbackFunction(not_all),

        errorMsg = "Feedback evaluation Error: \n%@";

    // this is the point of entry for evaluateFeedbackRules
    (function(){
      try {
        //var script = CoffeeScript.compile(expression,{thing: 10});
        eval(expression);
      }
      catch(e) {
        errorMsg = errorMsg.fmt(e);
        if (console && typeof console.log === 'function') {
          console.log(errorMsg);
        }
        alert(errorMsg);
      }
    }).call(self);

  }
});

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Link } from 'react-router';
// import { browserHistory } from 'react-redux'

class NavigationAuthorize extends Component{
  LogOut() {
    console.log('Good Bye!');
    localStorage.removeItem('token');
    // browserHistory.push('/')
  }

  render() {
    return (

                            <button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigation-index">
                                    Toggle navigation

                            </button>
                            <Link to="/" className="brand logo-container">

                            </Link>

                                  <Link to="notifications">notifications</Link>

                                    <Link to="profile"> account_circle My Profile</Link>

                                    <Link to="share-idea"> add_circle Share Idea </Link>

                                              <Link to="explore">explore Explore</Link>

                                    <Link to="/" onClick={this.LogOut.bind(this)}> Sign Out </Link>

    )
  }

}

export default NavigationAuthorize
<commit_msg>check<commit_after>import React, { Component } from 'react';
import { Link } from 'react-router';
// import { browserHistory } from 'react-redux'

class NavigationAuthorize extends Component{
  LogOut() {
    console.log('Good Bye!');
    localStorage.removeItem('token');
    // browserHistory.push('/')
  }

  render() {
    return (

                            <button type="button" className="navbar-toggle" data-toggle="collapse" data-target="#navigation-index">
                                    Toggle navigation

                            </button>
                            <Link to="/" className="brand logo-container">

                            </Link>

                                {/*

                                  <Link to="notifications">notifications</Link>

 */}

                                    <Link to="profile"> account_circle My Profile</Link>

                                    <Link to="share-idea"> add_circle Share Idea </Link>

                                              <Link to="explore">explore Explore</Link>

                                    <Link to="/" onClick={this.LogOut.bind(this)}> Sign Out </Link>

    )
  }

}

export default NavigationAuthorize
<|endoftext|>


<commit_before>import Immutable from 'immutable';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import React, { Component } from 'react';
import { PropTypes } from 'prop-types';

import { fetchRequiredActions } from 'base';

import * as Actions from './actions';
import <%= name %>Component from './components/';
import styles from './styles.css';

export class <%= name %> extends Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
    <%= name %>Model: PropTypes.instanceOf(Immutable.Record)
  };

  static requiredActions = [];

  constructor (props) {
    super(props);
    this.actions = bindActionCreators(Actions, props.dispatch);
  }

  render () {
    let props = this.props.<%= name  %>Model;
    props.name = '<%= name  %>';

    return (
      <div className={ styles.<%= name %>  }>
        <<%= name %>Component name={ props.name } />

    );
  }

}

export default connect(
  (state) => ({ <%= name %>Model: state.<%= name %> })
)(<%= name %>);
<commit_msg>Fix classname<commit_after>import Immutable from 'immutable';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import React, { Component } from 'react';
import { PropTypes } from 'prop-types';

import * as Actions from './actions';
import <%= name %>Component from './components/';
import styles from './styles.css';

class <%= name %> extends Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
    <%= name %>Model: PropTypes.instanceOf(Immutable.Record)
  };

  static requiredActions = [];

  constructor (props) {
    super(props);
    this.actions = bindActionCreators(Actions, props.dispatch);
  }

  render () {
    let props = this.props.<%= name  %>Model;
    props.name = '<%= name  %>';

    return (
      <div className={ styles.<%= name %>  }>
        <<%= name %>Component name={ props.name } />

    );
  }

}

export default connect(
  (state) => ({ <%= name %>Model: state.<%= name %> })
)(<%= name %>);
<|endoftext|>


<commit_before>(function () {
    'use strict';

    angular
        .module('dragscroll')
        .directive('dragScroll', DragScroll);

    DragScroll.$inject = ['$document', '$window'];

    /* @ngInject */
    function DragScroll($document, $window) {
        //Usage:
        //
Lorem ipsum dolor sit amet

        var directive = {
            scope: false,
            restrict: 'A',
            link: function($scope, $element, $attributes, vm) {
                var pushed = 0;
                var axis = $attributes.axis || false;
                var lastClientX;
                var lastClientY;

                // Set event listeners
                $element.on('mousedown', handleMouseDown);
                angular.element($window).on('mouseup', handleMouseUp);
                angular.element($window).on('mousemove', handleMouseMove);

                // Handle destroy event
                $scope.$on('$destroy', destroy);

                /**
                 * Handles mousedown event
                 * @param {object} e MouseDown event
                 */
                function handleMouseDown (e) {
                    var dragAllowed = !('prevent-drag' in e.target.attributes);

                    if(dragAllowed) {
                        pushed = 1;
                        lastClientX = e.clientX;
                        lastClientY = e.clientY;

                        //e.preventDefault();
                        e.stopPropagation();
                    }
                }

                /**
                 * Handles mouseup event
                 * @param {object} e MouseUp event
                 */
                function handleMouseUp () {
                    pushed = 0;
                }

                /**
                 * Handles mousemove event
                 * @param {object} e MouseMove event
                 */
                function handleMouseMove (e) {

                    if (pushed) {
                        if(!axis || axis === 'x') {
                            $element[0].scrollLeft -= (-lastClientX + (lastClientX = e.clientX));
                        }
                        if(!axis || axis === 'y') {
                            $element[0].scrollTop -= (-lastClientY + (lastClientY = e.clientY));
                        }
                    }

                }

                /**
                 * Destroys all the event listeners
                 */
                function destroy () {
                    $element.off('mousedown', handleMouseDown);
                    angular.element($window).off('mouseup', handleMouseUp);
                    angular.element($window).off('mousemove', handleMouseMove);
                }

            }
        };
        return directive;
    }

})();
<commit_msg>Better events and text selection<commit_after>(function () {
    'use strict';

    angular
        .module('dragscroll')
        .directive('dragScroll', DragScroll);

    DragScroll.$inject = ['$document', '$window', '$parse'];

    /* @ngInject */
    function DragScroll($document, $window, $parse) {
        //Usage:
        //
Lorem ipsum dolor sit amet

        var directive = {
            scope: false,
            restrict: 'A',
            link: function($scope, $element, $attributes, vm) {
                var allowedClickOffset = 5;
                var pushed = false;
                var onDragStart = $parse($attributes.onDragStart);
                var onDragEnd = $parse($attributes.onDragEnd);
                var axis = $attributes.axis || false;
                var startClientX;
                var startClientY;
                var lastClientX;
                var lastClientY;

                // Set event listeners
                $element.on('mousedown', handleMouseDown);

                // Set destroy listener
                $scope.$on('$destroy', destroy);

                /**
                 * Sets the event listeners for the mouseup and mousedown events
                 */
                function setDragListeners () {
                    angular.element($window).on('mouseup', handleMouseUp);
                    angular.element($window).on('mousemove', handleMouseMove);
                }

                /**
                 * Removes the event listeners for the mouseup and mousedown events
                 */
                function removeDragListeners () {
                    angular.element($window).off('mouseup', handleMouseUp);
                    angular.element($window).off('mousemove', handleMouseMove);
                }

                /**
                 * Handles mousedown event
                 * @param {object} e MouseDown event
                 */
                function handleMouseDown (e) {

                    $scope.$apply(function() {
                        onDragStart($scope);
                    });

                    // Set mouse drag listeners
                    setDragListeners();

                    // Set 'pushed' state
                    pushed = true;
                    lastClientX = startClientX = e.clientX;
                    lastClientY = startClientY = e.clientY;

                    clearSelection();

                    e.preventDefault();
                    e.stopPropagation();
                }

                /**
                 * Handles mouseup event
                 * @param {object} e MouseUp event
                 */
                function handleMouseUp (e) {
                    var selectable = ('drag-scroll-text' in e.target.attributes);
                    var withinXConstraints = (e.clientX >= (startClientX - allowedClickOffset) && e.clientX <= (startClientX + allowedClickOffset));
                    var withinYConstraints = (e.clientY >= (startClientY - allowedClickOffset) && e.clientY <= (startClientY + allowedClickOffset));

                    // Set 'pushed' state
                    pushed = false;

                    // Check if cursor falls within X and Y axis constraints
                    if(selectable && withinXConstraints && withinYConstraints) {
                        // If so, select the text inside the target element
                        selectText(e.target);
                    }

                    $scope.$apply(function() {
                        onDragEnd($scope);
                    });

                    removeDragListeners();
                }

                /**
                 * Handles mousemove event
                 * @param {object} e MouseMove event
                 */
                function handleMouseMove (e) {
                    if (pushed) {
                        if(!axis || axis === 'x') {
                            $element[0].scrollLeft -= (-lastClientX + (lastClientX = e.clientX));
                        }
                        if(!axis || axis === 'y') {
                            $element[0].scrollTop -= (-lastClientY + (lastClientY = e.clientY));
                        }
                    }

                    e.preventDefault();
                }

                /**
                 * Destroys all the event listeners
                 */
                function destroy () {
                    $element.off('mousedown', handleMouseDown);
                    angular.element($window).off('mouseup', handleMouseUp);
                    angular.element($window).off('mousemove', handleMouseMove);
                }

                /**
                 * Selects text for a specific element
                 * @param {object} element Selected element
                 */
                function selectText (element) {
                    if ($window.document.selection) {
                        var range = $window.document.body.createTextRange();
                        range.moveToElementText(element);
                        range.select();
                    } else if ($window.getSelection) {
                        var range = $window.document.createRange();
                        range.selectNode(element);
                        $window.getSelection().addRange(range);
                    }
                }

                /**
                 * Clears text selection
                 */
                function clearSelection () {
                    if ($window.getSelection) {
                        if ($window.getSelection().empty) {  // Chrome
                            $window.getSelection().empty();
                        } else if ($window.getSelection().removeAllRanges) {  // Firefox
                            $window.getSelection().removeAllRanges();
                        }
                    } else if ($document.selection) {  // IE?
                        $document.selection.empty();
                    }
                }

            }
        };
        return directive;

    }

})();
<|endoftext|>