<commit_before>/**
    @constructor
    @param {no.View} view
    @param {string} layout_id
    @param {Object} params
*/
no.Update = function(view, layout_id, params) {
    this.id = no.Update.id++;

    this.view = view;
    this.layout_id = layout_id;
    this.params = params;

    this.layout = no.layout.get( layout_id );

    this.prepare();
    this.request();
};

/** @type {number} */
no.Update.id = 0;

// ----------------------------------------------------------------------------------------------------------------- //

no.Update.prototype.prepare = function() {
    this.requests = {};

    var tree = this.tree = no.View.getLayoutTree( this.view.id, this );

    var params = this.params;

    var that = this;
    no.Update.walkLeafs(tree, function(view_id, type) {
        var view_info = no.View.info( view_id );
        var models = view_info.models;
        if (view_info.async) {
            that.createAsyncViewRequest(view_id, params);
        } else {
            that.addItemsToMainRequest(models, params);
        }
    });
};

/**
    @param {!Object} obj
    @param {function} callback
*/
no.Update.walkLeafs = function(obj, callback) {
    for (var key in obj) {
        var value = obj[key];
        if (typeof value !== 'object') {
            callback(key, value);
        } else {
            no.Update.walkLeafs(value, callback);
        }
    }
};

/**
    @param {Array.<string>} model_ids Model identifiers.
    @param {Object} params Model get params.
*/
no.Update.prototype.addItemsToMainRequest = function(model_ids, params) {
    var request_id = "all";
    var request = this.requests[request_id];

    if (!request) {
        request = ((this.requests[request_id] = { models: model_ids, params: params } ));
    } else {
        request.models = request.models.concat(model_ids);
        no.extend(request.params, params); // Расширяем параметры для запроса моделей.
    }
};

/**
    @param {no.View} view View instance.
    @param {Object} params Model get params.
*/
no.Update.prototype.createAsyncViewRequest = function(view_id, params) {
    var request = {
        view_id: view_id,
        models: no.View.info(view_id).models,
        params: params
    };
    var request_id = view_id;   // Использует view_id в качестве id запроса, чтобы избежать конфликтов с другими запросами.
                                // XXX плохой выбор для request_id, могут быть конфликты
    this.requests[request_id] = request;
};

// ----------------------------------------------------------------------------------------------------------------- //

no.Update.prototype.request = function() {
    var that = this;
    var requests = this.requests;
    var main_request = new no.Request([ requests.all ]);

    // Вначале запускаем основной запрос, потом идут остальные.
    main_request
        .start()
        .then(function() {
            that.render(that.view, main_request);
        })
        .then(function() {
            var keys = no.object.keys(requests);
            for (var i = 0; i < keys.length; i++) {
                var key = keys[i];
                if (key === "all") {
                    continue;
                }

                // Создаём no.Request на каждый асинхронный блок.
                (function(req) {
                    var async = new no.Request([ req ]);
                    async
                        .start()
                        .then(function() {
                            var view = no.View.get(req.view_id, req.params);
                            that.render(view, async);
                        });
                })(requests[key]);
            }
        });
};

no.Update.prototype.render = function(view, request) {
    var groups = request.groups;
    var viewsTree = [];
    view.getUpdateTrees(this, viewsTree);

    var tree = {
        views: viewsTree,
        models: {},
        params: {}
    };
    var models = tree.models;
    var params = tree.params;
    for (var i = 0, l = groups.length; i < l; i++) {
        var group = groups[i];
        for (var j = 0, m = group.models.length; j < m; j++) {
            var model_id = group.models[j];
            var key = no.Model.key(model_id, group.params);
            models[model_id] = no.Model.get(model_id, key).data;
            params[model_id] = group.params;
        }
    }

    // console.time('template');
    var html = stylesheet( tree ); // FIXME: Нужно проверять, что update не нужен и ничего не делать.
    // console.timeEnd('template');
    var div = document.createElement('div');
    div.innerHTML = html;

    var node = div.firstChild;
    this.update(view, node);
}

/**
    @param {Element} node
*/
no.Update.prototype.update = function(root_view, node) {
    /*
    if (this.canceled || this.id < no.Update.id) { // Запущен какой-то новый update, этот выполнять уже ненужно.
        return;
    }
    */

    /*
    if (!this.hasAllData()) {
        // ERROR.
        return;
    }
    */

    var that = this;
    root_view.processTree(function(view) {
        if (view.needUpdate(that)) {
            view.update(node, that, true);
            return false;
        }
    });
};

// ----------------------------------------------------------------------------------------------------------------- //

<commit_msg>New Yater.run syntax<commit_after>/**
    @constructor
    @param {no.View} view
    @param {string} layout_id
    @param {Object} params
*/
no.Update = function(view, layout_id, params) {
    this.id = no.Update.id++;

    this.view = view;
    this.layout_id = layout_id;
    this.params = params;

    this.layout = no.layout.get( layout_id );

    this.prepare();
    this.request();
};

/** @type {number} */
no.Update.id = 0;

// ----------------------------------------------------------------------------------------------------------------- //

no.Update.prototype.prepare = function() {
    this.requests = {};

    var tree = this.tree = no.View.getLayoutTree( this.view.id, this );

    var params = this.params;

    var that = this;
    no.Update.walkLeafs(tree, function(view_id, type) {
        var view_info = no.View.info( view_id );
        var models = view_info.models;
        if (view_info.async) {
            that.createAsyncViewRequest(view_id, params);
        } else {
            that.addItemsToMainRequest(models, params);
        }
    });
};

/**
    @param {!Object} obj
    @param {function} callback
*/
no.Update.walkLeafs = function(obj, callback) {
    for (var key in obj) {
        var value = obj[key];
        if (typeof value !== 'object') {
            callback(key, value);
        } else {
            no.Update.walkLeafs(value, callback);
        }
    }
};

/**
    @param {Array.<string>} model_ids Model identifiers.
    @param {Object} params Model get params.
*/
no.Update.prototype.addItemsToMainRequest = function(model_ids, params) {
    var request_id = "all";
    var request = this.requests[request_id];

    if (!request) {
        request = ((this.requests[request_id] = { models: model_ids, params: params } ));
    } else {
        request.models = request.models.concat(model_ids);
        no.extend(request.params, params); // Расширяем параметры для запроса моделей.
    }
};

/**
    @param {no.View} view View instance.
    @param {Object} params Model get params.
*/
no.Update.prototype.createAsyncViewRequest = function(view_id, params) {
    var request = {
        view_id: view_id,
        models: no.View.info(view_id).models,
        params: params
    };
    var request_id = view_id;   // Использует view_id в качестве id запроса, чтобы избежать конфликтов с другими запросами.
                                // XXX плохой выбор для request_id, могут быть конфликты
    this.requests[request_id] = request;
};

// ----------------------------------------------------------------------------------------------------------------- //

no.Update.prototype.request = function() {
    var that = this;
    var requests = this.requests;
    var main_request = new no.Request([ requests.all ]);

    // Вначале запускаем основной запрос, потом идут остальные.
    main_request
        .start()
        .then(function() {
            that.render(that.view, main_request);
        })
        .then(function() {
            var keys = no.object.keys(requests);
            for (var i = 0; i < keys.length; i++) {
                var key = keys[i];
                if (key === "all") {
                    continue;
                }

                // Создаём no.Request на каждый асинхронный блок.
                (function(req) {
                    var async = new no.Request([ req ]);
                    async
                        .start()
                        .then(function() {
                            var view = no.View.get(req.view_id, req.params);
                            that.render(view, async);
                        });
                })(requests[key]);
            }
        });
};

no.Update.prototype.render = function(view, request) {
    var groups = request.groups;
    var viewsTree = [];
    view.getUpdateTrees(this, viewsTree);

    var tree = {
        views: viewsTree,
        models: {},
        params: {}
    };
    var models = tree.models;
    var params = tree.params;
    for (var i = 0, l = groups.length; i < l; i++) {
        var group = groups[i];
        for (var j = 0, m = group.models.length; j < m; j++) {
            var model_id = group.models[j];
            var key = no.Model.key(model_id, group.params);
            models[model_id] = no.Model.get(model_id, key).data;
            params[model_id] = group.params;
        }
    }

    // console.time('template');
    var html = Yater.run( tree ); // FIXME: Нужно проверять, что update не нужен и ничего не делать.
    // console.timeEnd('template');
    var div = document.createElement('div');
    div.innerHTML = html;

    var node = div.firstChild;
    this.update(view, node);
}

/**
    @param {Element} node
*/
no.Update.prototype.update = function(root_view, node) {
    /*
    if (this.canceled || this.id < no.Update.id) { // Запущен какой-то новый update, этот выполнять уже ненужно.
        return;
    }
    */

    /*
    if (!this.hasAllData()) {
        // ERROR.
        return;
    }
    */

    var that = this;
    root_view.processTree(function(view) {
        if (view.needUpdate(that)) {
            view.update(node, that, true);
            return false;
        }
    });
};

// ----------------------------------------------------------------------------------------------------------------- //

<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

// ************************************************************************************************
// Constants

const CLASS_ID = Components.ID("{9589DC0D-9709-4578-883E-D393452B3611}");
const CLASS_NAME = "Firebug Annotation Service";
const CONTRACT_ID = "@joehewitt.com/firebug-annotation-service;1";

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);

// ************************************************************************************************
// Annotaion service implementation

var FBTrace = null;

/**
 * @class Represents an internal Firebug annotation service. This service is used to
 * annotate sites with an info whether Firebug should be activated for them or not.
 */
function AnnotationService()
{
    this.wrappedJSObject = this;

    FBTrace = Cc["@joehewitt.com/firebug-trace-service;1"]
       .getService(Ci.nsISupports).wrappedJSObject.getTracer("extensions.firebug");

    // Get annotation file stored within the profile directory.
    this.file = dirService.get("ProfD", Ci.nsIFile);
    this.file.append("firebug");
    this.file.append("annotations.json");

    // Load annotaions.
    this.initialize();
}

AnnotationService.prototype =
{
    annotations: [],

    setPageAnnotation: function(uri, value)
    {
        this.annotations[uri.spec] = value;
    },

    getPageAnnotation: function(uri)
    {
        return this.annotations[uri.spec];
    },

    pageHasAnnotation: function(uri)
    {
        return this.annotations[uri.spec] ? true : false;
    },

    removePageAnnotation: function(uri)
    {
        delete this.annotations[uri.spec];
    },

    getAnnotations: function()
    {
        return this.annotations[uri.spec];
    },

    clear: function()
    {
        this.annotations = [];
    },

    // Persistence
    initialize: function()
    {
        try
        {
            this.clear();

            if (!this.file.exists())
            {
                this.file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
                if (FBTrace.DBG_ANNOTATIONS)
                    FBTrace.sysout("AnnotationService.initialize; Annotaions file created " +
                        this.file.path);
                return;
            }

            var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
                .createInstance(Ci.nsIFileInputStream);
            var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
                .createInstance(Ci.nsIConverterInputStream);

            // Initialize input stream.
            inputStream.init(this.file, 0x01 | 0x08, 0666, 0); // read, create
            cstream.init(inputStream, "UTF-8", 0, 0);

            // Load annotations.
            var data = {};
            cstream.readString(-1, data);
            if (!data.value.length)
                return;

            // Convert to map for faster lookup.
            var arr = eval(data.value);
            if (!arr)
                return;

            for (var i=0; i<arr.length; i++)
                this.annotations[arr[i].uri] = arr[i].value;

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.initialize; Annotations loaded from " +
                    this.file.path);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.initialize; EXCEPTION", err);
        }
    },

    flush: function()
    {
        try
        {
            // Initialize output stream.
            var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
                .createInstance(Ci.nsIFileOutputStream);
            outputStream.init(this.file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate

            // Convert data to JSON.
            var arr = [];
            for (var uri in this.annotations)
                arr.push("{" + "'uri': '" + uri + "', 'value': '" + this.annotations[uri]+ "'}");
            var jsonString = "[\n" + arr.join(",\n") + "\n]\n";

            // Store annotations.
            outputStream.write(jsonString, jsonString.length);
            outputStream.close();

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.initialize; Annotations stored to " +
                    this.file.path, jsonString);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.flush; EXCEPTION", err);
        }
    },

    /* nsISupports */
    QueryInterface: function(iid)
    {
        if (iid.equals(Ci.nsISupports))
            return this;

        throw Cr.NS_ERROR_NO_INTERFACE;
    }
};

// ************************************************************************************************
// Service factory

var gServiceSingleton = null;
var AnnotationsFactory =
{
    createInstance: function (outer, iid)
    {
        if (outer != null)
            throw Cr.NS_ERROR_NO_AGGREGATION;

        if (iid.equals(Ci.nsISupports))
        {
            if (!gServiceSingleton)
                gServiceSingleton = new AnnotationService();
            return gServiceSingleton.QueryInterface(iid);
        }

        throw Cr.NS_ERROR_NO_INTERFACE;
    },

    QueryInterface: function(iid)
    {
        if (iid.equals(Ci.nsISupports) ||
            iid.equals(Ci.nsISupportsWeakReference) ||
            iid.equals(Ci.nsIFactory))
            return this;

        throw Cr.NS_ERROR_NO_INTERFACE;
    }
};

// ************************************************************************************************
// Module implementation

var AnnotationsModule =
{
    registerSelf: function (compMgr, fileSpec, location, type)
    {
        compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME,
            CONTRACT_ID, fileSpec, location, type);
    },

    unregisterSelf: function(compMgr, fileSpec, location)
    {
        compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
        compMgr.unregisterFactoryLocation(CLASS_ID, location);
    },

    getClassObject: function (compMgr, cid, iid)
    {
        if (!iid.equals(Ci.nsIFactory))
            throw Cr.NS_ERROR_NOT_IMPLEMENTED;

        if (cid.equals(CLASS_ID))
            return AnnotationsFactory;

        throw Cr.NS_ERROR_NO_INTERFACE;
    },

    canUnload: function(compMgr)
    {
        return true;
    }
};

// ************************************************************************************************

function NSGetModule(compMgr, fileSpec)
{
    return AnnotationsModule;
}
<commit_msg>Adapt FireStarter to the new Annotation Service.<commit_after>/* See license.txt for terms of usage */

// ************************************************************************************************
// Constants

const CLASS_ID = Components.ID("{9589DC0D-9709-4578-883E-D393452B3611}");
const CLASS_NAME = "Firebug Annotation Service";
const CONTRACT_ID = "@joehewitt.com/firebug-annotation-service;1";

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);

// ************************************************************************************************
// Annotaion service implementation

var FBTrace = null;

/**
 * @class Represents an internal Firebug annotation service. This service is used to
 * annotate sites with an info whether Firebug should be activated for them or not.
 */
function AnnotationService()
{
    this.wrappedJSObject = this;

    FBTrace = Cc["@joehewitt.com/firebug-trace-service;1"]
       .getService(Ci.nsISupports).wrappedJSObject.getTracer("extensions.firebug");

    // Get annotation file stored within the profile directory.
    this.file = dirService.get("ProfD", Ci.nsIFile);
    this.file.append("firebug");
    this.file.append("annotations.json");

    // Load annotaions.
    this.initialize();
}

AnnotationService.prototype =
{
    annotations: [],

    setPageAnnotation: function(uri, value)
    {
        this.annotations[uri.spec] = value;
    },

    getPageAnnotation: function(uri)
    {
        return this.annotations[uri.spec];
    },

    pageHasAnnotation: function(uri)
    {
        return this.annotations[uri.spec] ? true : false;
    },

    removePageAnnotation: function(uri)
    {
        delete this.annotations[uri.spec];
    },

    getAnnotations: function()
    {
        return this.annotations;
    },

    clear: function()
    {
        this.annotations = [];
    },

    // Persistence
    initialize: function()
    {
        try
        {
            this.clear();

            if (!this.file.exists())
            {
                this.file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
                if (FBTrace.DBG_ANNOTATIONS)
                    FBTrace.sysout("AnnotationService.initialize; Annotaions file created " +
                        this.file.path);
                return;
            }

            var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
                .createInstance(Ci.nsIFileInputStream);
            var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
                .createInstance(Ci.nsIConverterInputStream);

            // Initialize input stream.
            inputStream.init(this.file, 0x01 | 0x08, 0666, 0); // read, create
            cstream.init(inputStream, "UTF-8", 0, 0);

            // Load annotations.
            var data = {};
            cstream.readString(-1, data);
            if (!data.value.length)
                return;

            // Convert to map for faster lookup.
            var arr = eval(data.value);
            if (!arr)
                return;

            for (var i=0; i<arr.length; i++)
                this.annotations[arr[i].uri] = arr[i].value;

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.initialize; Annotations loaded from " +
                    this.file.path);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.initialize; EXCEPTION", err);
        }
    },

    flush: function()
    {
        try
        {
            // Initialize output stream.
            var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
                .createInstance(Ci.nsIFileOutputStream);
            outputStream.init(this.file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate

            // Convert data to JSON.
            var arr = [];
            for (var uri in this.annotations)
                arr.push("{" + "'uri': '" + uri + "', 'value': '" + this.annotations[uri]+ "'}");
            var jsonString = "[\n" + arr.join(",\n") + "\n]\n";

            // Store annotations.
            outputStream.write(jsonString, jsonString.length);
            outputStream.close();

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.initialize; Annotations stored to " +
                    this.file.path, jsonString);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.flush; EXCEPTION", err);
        }
    },

    /* nsISupports */
    QueryInterface: function(iid)
    {
        if (iid.equals(Ci.nsISupports))
            return this;

        throw Cr.NS_ERROR_NO_INTERFACE;
    }
};

// ************************************************************************************************
// Service factory

var gServiceSingleton = null;
var AnnotationsFactory =
{
    createInstance: function (outer, iid)
    {
        if (outer != null)
            throw Cr.NS_ERROR_NO_AGGREGATION;

        if (iid.equals(Ci.nsISupports))
        {
            if (!gServiceSingleton)
                gServiceSingleton = new AnnotationService();
            return gServiceSingleton.QueryInterface(iid);
        }

        throw Cr.NS_ERROR_NO_INTERFACE;
    },

    QueryInterface: function(iid)
    {
        if (iid.equals(Ci.nsISupports) ||
            iid.equals(Ci.nsISupportsWeakReference) ||
            iid.equals(Ci.nsIFactory))
            return this;

        throw Cr.NS_ERROR_NO_INTERFACE;
    }
};

// ************************************************************************************************
// Module implementation

var AnnotationsModule =
{
    registerSelf: function (compMgr, fileSpec, location, type)
    {
        compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME,
            CONTRACT_ID, fileSpec, location, type);
    },

    unregisterSelf: function(compMgr, fileSpec, location)
    {
        compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
        compMgr.unregisterFactoryLocation(CLASS_ID, location);
    },

    getClassObject: function (compMgr, cid, iid)
    {
        if (!iid.equals(Ci.nsIFactory))
            throw Cr.NS_ERROR_NOT_IMPLEMENTED;

        if (cid.equals(CLASS_ID))
            return AnnotationsFactory;

        throw Cr.NS_ERROR_NO_INTERFACE;
    },

    canUnload: function(compMgr)
    {
        return true;
    }
};

// ************************************************************************************************

function NSGetModule(compMgr, fileSpec)
{
    return AnnotationsModule;
}
<|endoftext|>


<commit_before>/* eslint-disable no-console, no-underscore-dangle, import/no-extraneous-dependencies */
import React from 'react';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';
import zipWith from 'lodash/zipWith';

import getMountableComponent from './getMountableComponent';

export default class Region extends React.Component {
  static propTypes = {
    children: PropTypes.function,
    className: PropTypes.string,
    name: PropTypes.string.isRequired,
    uniqueKey: PropTypes.string,
    data: PropTypes.any,
  };

  static contextTypes = {
    app: PropTypes.object,
  };

  static sendProps(appInstance, props) {
    const regionService = appInstance.get(appInstance.options.providerNames.region);

    if (!regionService) {
      return;
    }

    regionService.emit(props);
  }

  constructor(props, context) {
    super(props, context);

    if (context.app) {
      const rootApp = context.app.getRootApp();
      const list = rootApp._appsCollection.filter(({ regions }) => {
        return regions.some(name => props.name === name);
      });

      this.state = {
        list,
        listForRendering: this.getListForRendering(list, rootApp)
      };
    } else {
      this.state = {
        list: [], // array of apps ==> { name, instance }
        listForRendering: [] // array of { name, Component } objects
      };
    }
  }

  getListForRendering(list, rootApp, listForRendering = []) {
    const {
      uniqueKey,
      data
    } = this.props;

    return list
      .map((item) => {
        const {
          name,
          weight,
          multi
        } = item;
        const isPresent = listForRendering.some((w) => {
          return w.name === name;
        });

        // @TODO: take care of removal in streamed list too?
        if (isPresent) {
          return null;
        }

        const regionArgs = uniqueKey
          ? [this.props.name, uniqueKey]
          : [this.props.name];

        if (
          uniqueKey &&
          !rootApp.hasAppInstance(name, ...regionArgs)
        ) {
          rootApp.instantiateApp(name, ...regionArgs);
        }

        const instance = rootApp.getAppInstance(name, ...regionArgs);

        if (instance) {
          Region.sendProps(instance, {
            name: this.props.name,
            uniqueKey,
            data,
          });
        }

        return {
          name,
          weight,
          instance,
          multi,
          Component: getMountableComponent(instance),
        };
      })
      .filter(item => !!item)
      .concat(listForRendering)
      .sort((a, b) => a.weight - b.weight);
  }

  shouldComponentUpdate(nextProps, nextState) {
    let shouldUpdate = !isEqual(this.props, nextProps);

    if (!shouldUpdate) {
      const { listForRendering } = nextState;
      shouldUpdate = shouldUpdate || this.state.listForRendering.length !== listForRendering.length;
      shouldUpdate = shouldUpdate ||
        zipWith(this.state.listForRendering, listForRendering, (a, b) => a.name === b.name)
          .some(value => !value);
    }

    return shouldUpdate;
  }

  componentDidMount() {
    if (!this.context.app) {
      return;
    }

    const rootApp = this.context.app.getRootApp();

    this.rootApp = rootApp;
    const apps$ = rootApp.getApps$(
      this.props.name,
      this.props.uniqueKey
    );

    this._subscription = apps$.subscribe({
      next: (list) => {
        this.setState({
          list,
          listForRendering: this.getListForRendering(list, rootApp, this.state.listForRendering)
        });
      },
      error: (err) => {
        console.warn(`Subscription error for <Region name="${this.name}" />:`, err);
      }
    });
  }

  componentWillReceiveProps(nextProps) {
    const {
      name = this.props.name,
      uniqueKey = this.props.uniqueKey,
      data = this.props.data,
    } = nextProps;

    this.state.listForRendering
      .filter(item => item.instance)
      .forEach(item => Region.sendProps(item.instance, {
        name,
        uniqueKey,
        data,
      }));
  }

  componentWillUnmount() {
    if (this._subscription) {
      this._subscription.unsubscribe();
    }

    if (this.rootApp) {
      this.state.listForRendering
        .filter(item => item.multi)
        .forEach((item) => {
          this.rootApp.destroyApp(
            item.name,
            this.props.name,
            this.props.uniqueKey
          );
        });
    }
  }

  render() {
    const { listForRendering } = this.state;

    if (listForRendering.length === 0) {
      return null;
    }

    const { className, children, ...props } = this.props;

    if (typeof children === 'function') {
      return (

          {children(listForRendering, props)}

      );
    }

    return (

        {listForRendering.map((item) => {
          const { Component, name } = item;

          return (
            <Component key={`app-${name}`} />
          );
        })}

    );
  }
}
<commit_msg>Fix typo in `children` prop type (#434)<commit_after>/* eslint-disable no-console, no-underscore-dangle, import/no-extraneous-dependencies */
import React from 'react';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';
import zipWith from 'lodash/zipWith';

import getMountableComponent from './getMountableComponent';

export default class Region extends React.Component {
  static propTypes = {
    children: PropTypes.func,
    className: PropTypes.string,
    name: PropTypes.string.isRequired,
    uniqueKey: PropTypes.string,
    data: PropTypes.any,
  };

  static contextTypes = {
    app: PropTypes.object,
  };

  static sendProps(appInstance, props) {
    const regionService = appInstance.get(appInstance.options.providerNames.region);

    if (!regionService) {
      return;
    }

    regionService.emit(props);
  }

  constructor(props, context) {
    super(props, context);

    if (context.app) {
      const rootApp = context.app.getRootApp();
      const list = rootApp._appsCollection.filter(({ regions }) => {
        return regions.some(name => props.name === name);
      });

      this.state = {
        list,
        listForRendering: this.getListForRendering(list, rootApp)
      };
    } else {
      this.state = {
        list: [], // array of apps ==> { name, instance }
        listForRendering: [] // array of { name, Component } objects
      };
    }
  }

  getListForRendering(list, rootApp, listForRendering = []) {
    const {
      uniqueKey,
      data
    } = this.props;

    return list
      .map((item) => {
        const {
          name,
          weight,
          multi
        } = item;
        const isPresent = listForRendering.some((w) => {
          return w.name === name;
        });

        // @TODO: take care of removal in streamed list too?
        if (isPresent) {
          return null;
        }

        const regionArgs = uniqueKey
          ? [this.props.name, uniqueKey]
          : [this.props.name];

        if (
          uniqueKey &&
          !rootApp.hasAppInstance(name, ...regionArgs)
        ) {
          rootApp.instantiateApp(name, ...regionArgs);
        }

        const instance = rootApp.getAppInstance(name, ...regionArgs);

        if (instance) {
          Region.sendProps(instance, {
            name: this.props.name,
            uniqueKey,
            data,
          });
        }

        return {
          name,
          weight,
          instance,
          multi,
          Component: getMountableComponent(instance),
        };
      })
      .filter(item => !!item)
      .concat(listForRendering)
      .sort((a, b) => a.weight - b.weight);
  }

  shouldComponentUpdate(nextProps, nextState) {
    let shouldUpdate = !isEqual(this.props, nextProps);

    if (!shouldUpdate) {
      const { listForRendering } = nextState;
      shouldUpdate = shouldUpdate || this.state.listForRendering.length !== listForRendering.length;
      shouldUpdate = shouldUpdate ||
        zipWith(this.state.listForRendering, listForRendering, (a, b) => a.name === b.name)
          .some(value => !value);
    }

    return shouldUpdate;
  }

  componentDidMount() {
    if (!this.context.app) {
      return;
    }

    const rootApp = this.context.app.getRootApp();

    this.rootApp = rootApp;
    const apps$ = rootApp.getApps$(
      this.props.name,
      this.props.uniqueKey
    );

    this._subscription = apps$.subscribe({
      next: (list) => {
        this.setState({
          list,
          listForRendering: this.getListForRendering(list, rootApp, this.state.listForRendering)
        });
      },
      error: (err) => {
        console.warn(`Subscription error for <Region name="${this.name}" />:`, err);
      }
    });
  }

  componentWillReceiveProps(nextProps) {
    const {
      name = this.props.name,
      uniqueKey = this.props.uniqueKey,
      data = this.props.data,
    } = nextProps;

    this.state.listForRendering
      .filter(item => item.instance)
      .forEach(item => Region.sendProps(item.instance, {
        name,
        uniqueKey,
        data,
      }));
  }

  componentWillUnmount() {
    if (this._subscription) {
      this._subscription.unsubscribe();
    }

    if (this.rootApp) {
      this.state.listForRendering
        .filter(item => item.multi)
        .forEach((item) => {
          this.rootApp.destroyApp(
            item.name,
            this.props.name,
            this.props.uniqueKey
          );
        });
    }
  }

  render() {
    const { listForRendering } = this.state;

    if (listForRendering.length === 0) {
      return null;
    }

    const { className, children, ...props } = this.props;

    if (typeof children === 'function') {
      return (

          {children(listForRendering, props)}

      );
    }

    return (

        {listForRendering.map((item) => {
          const { Component, name } = item;

          return (
            <Component key={`app-${name}`} />
          );
        })}

    );
  }
}
<|endoftext|>


<commit_before>var fs = require('fs');

var gm = require('./Gentrimap.node.js');
var gmdb = new gm.DB();
var merge = gm.merge;

var data = readCSV('../../Daten/Daten normalisiert/Proto_CSV_Dateien/alter_1992_2011.csv', ';', ['ZEIT', 'Anzahl', 'Anteil', 'Fert']);

var options = {
	geoIdFunction: function (obj) { switch (obj.RAUMID.length) {
		case 8:
			return obj.RAUMID;
		case 7:
			return '0'+obj.RAUMID;
		default:
			console.error('Unknown length: '+obj.RAUMID.length+' ('+obj.RAUMID+')');
		 	return undefined
	} },
	geoName: 'Planungsraum'
};

for (var year = 1992; year <= 2011; year++) {
	/*
	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl der Neugeborenen', valueFunction: function (obj) { return obj['Anzahl Neugeboren'] }, minValue:0
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl der 25-45 Jährigen', valueFunction: function (obj) { return obj['Anzahl der 25-45'] }, minValue:0
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl der 25-35 Jährigen', valueFunction: function (obj) { return obj['Anzahl der 25-35'] }, minValue:0
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl Einwohner insgesamt', valueFunction: function (obj) { return obj['Anzahl insgesamt'] }, minValue:0
	}));
	*/
	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der Neugeborenen', valueFunction: function (obj) { return obj['Anteil Neugeboren'] }, minValue:0, maxValue:3
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Fertilitätsrate', valueFunction: function (obj) { return obj['Fertilitaetsrate'] }, minValue:0, maxValue:4
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der 25-35 Jährigen', valueFunction: function (obj) { return obj['Anteil der 25-35'] }, minValue:0, maxValue:30
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der 25-45 Jährigen', valueFunction: function (obj) { return obj['Anteil der 25-45'] }, minValue:0, maxValue:60
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der 25-35 an 25-45 Jährigen', valueFunction: function (obj) { return obj['Anteil der 25-35 an 25-45'] }, minValue:25, maxValue:70
	}));
}

var data = readCSV('../../Daten/Daten normalisiert/Proto_CSV_Dateien/Sozialmonitoring PLR 2007-2009.csv', ';', ['A', 'L', 'N', 'M', 'J']);

var options = {
	geoIdFunction: function (obj) { switch (obj.Raum.length) {
		case 9:
			return '0'+obj.Raum.substr(0,7);
		case 8:
			return obj.Raum;
		case 7:
			return '0'+obj.Raum;
		default:
			console.error('Unknown length: '+obj.Raum.length+' ('+obj.Raum+')');
		 	return undefined
	} },
	geoName: 'Planungsraum'
};

for (var year = 2007; year <= 2009; year++) {
	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Arbeitslose in % der 15-65-Jährigen', valueFunction: function (obj) { return obj['Arbeitslose'] }, minValue:0, maxValue:21
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Arbeitslose unter 25 Jahren in % der 15-25-Jährigen', valueFunction: function (obj) { return obj['Arbeitslose unter 25 Jahren'] }, minValue:0, maxValue:13
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Langzeitarbeitslose', valueFunction: function (obj) { return obj['Langzeitarbeitslose'] }, minValue:0, maxValue:10
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Nichtarbeitslose Empfänger_innen von Existenzsicherungsleistungen', valueFunction: function (obj) { return obj['Nichtarbeitslose Empfaenger'] }, minValue:0, maxValue:40
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Nichterwerbsfähige Empfänger_innen von Existenzsicherungsleistungen unter 15 Jahren', valueFunction: function (obj) { return obj['Nichterwerbsfaehige Empfaenger'] }, minValue:0, maxValue:80
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Kinder und Jugendliche unter 18 Jahren mit Migrationshintergrund', valueFunction: function (obj) { return obj['Migrationshintergrund'] }, minValue:0, maxValue:90
	}));
}

gmdb.addGeo(readGeoJSON('./geo/Planungsraum_25833.geojson').features, {
	geoName: 'Planungsraum',
	geoIdFunction: function (obj) { return obj.SCHLUESSEL },
	synonyms:[
		["12103015","12103115"],
		["12103016","12103116"],
		["12103017","12103117"],
		["12103018","12103218"],
		["12103019","12103219"],
		["12103020","12103220"],
		["12214121","12214421"],
		["12214122","12214422"],
		["12214123","12214423"],
		["12214124","12214424"],
		["12214127","12214527"],
		["12214128","12214528"],
		["12302007","12302107"],
		["12302008","12302108"],
		["12302009","12302109"],
		["12302010","12302110"],
		["12302011","12302211"],
		["12302012","12302212"]
	]
});

gmdb.match();

fs.writeFileSync('../html/data.js', 'var data ='+JSON.stringify(gmdb.exportJSON(), null, '\t'), 'utf8');

function readCSV(filename, fieldSeparator, valueFields) {
	fieldSeparator = fieldSeparator || ';';
	valueFields = valueFields || [];

	var lines = fs.readFileSync(filename, 'utf8');
	lines = lines.replace(/[\n\r]+/g, '\r');
	lines = lines.replace(new RegExp('\;+\r', 'g'), '\r');
	lines = lines.split('\r');

	var headFields = lines[0].split(fieldSeparator);

	var r = [];
	for (var j = 0; j < headFields.length; j++) {
		var useThis = false;
		for (var k = 0; k < valueFields.length; k++) {
			if (headFields[j].substr(0, valueFields[k].length) == valueFields[k]) useThis = true;
		}
		if (useThis) r.push(headFields[j]);
	};
	valueFields = r;

	var result = [];
	for (var i = 1; i < lines.length; i++) {
		var line = lines[i];
		if (line.length > 0) {
			var fields = line.split(fieldSeparator);
			if (fields.length != headFields.length) console.error('Äääh: "'+line+'"');
			var obj = {};
			for (var j = 0; j < fields.length; j++) obj[headFields[j]] = fields[j];
			for (var j = 0; j < valueFields.length; j++) {
				var s = obj[valueFields[j]];
				s = s.replace(',','.');
				obj[valueFields[j]] = parseFloat(s);
			}
			result.push(obj);
		}
	}
	return result;
}

function readGeoJSON(filename) {
	var json = fs.readFileSync(filename, 'utf8');
	return JSON.parse(json);
}<commit_msg>cleaning up ... a little bit<commit_after>var fs = require('fs');

var gm = require('./Gentrimap.node.js');
var gmdb = new gm.DB();
var merge = gm.merge;

var data = readCSV('../../Daten/Daten normalisiert/Proto_CSV_Dateien/alter_1992_2011.csv', ';', ['ZEIT', 'Anzahl', 'Anteil', 'Fert']);

var options = {
	geoIdFunction: function (obj) {
		switch (obj.RAUMID.length) {
			case 8:
				return obj.RAUMID;
			case 7:
				return '0'+obj.RAUMID;
			default:
				console.error('Unknown length: '+obj.RAUMID.length+' ('+obj.RAUMID+')');
				return undefined
		}
	},
	geoName: 'Planungsraum'
};

for (var year = 1992; year <= 2011; year++) {
	/*
	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl der Neugeborenen', valueFunction: function (obj) { return obj['Anzahl Neugeboren'] }, minValue:0
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl der 25-45 Jährigen', valueFunction: function (obj) { return obj['Anzahl der 25-45'] }, minValue:0
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl der 25-35 Jährigen', valueFunction: function (obj) { return obj['Anzahl der 25-35'] }, minValue:0
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anzahl Einwohner insgesamt', valueFunction: function (obj) { return obj['Anzahl insgesamt'] }, minValue:0
	}));
	*/
	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der Neugeborenen', valueFunction: function (obj) { return obj['Anteil Neugeboren'] }, minValue:0, maxValue:3
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Fertilitätsrate', valueFunction: function (obj) { return obj['Fertilitaetsrate'] }, minValue:0, maxValue:4
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der 25-35 Jährigen', valueFunction: function (obj) { return obj['Anteil der 25-35'] }, minValue:0, maxValue:30
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der 25-45 Jährigen', valueFunction: function (obj) { return obj['Anteil der 25-45'] }, minValue:0, maxValue:60
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.ZEIT==year) },	year:year,
		tableName:'Anteil der 25-35 an 25-45 Jährigen', valueFunction: function (obj) { return obj['Anteil der 25-35 an 25-45'] }, minValue:25, maxValue:70
	}));
}

var data = readCSV('../../Daten/Daten normalisiert/Proto_CSV_Dateien/Sozialmonitoring PLR 2007-2009.csv', ';', ['A', 'L', 'N', 'M', 'J']);

var options = {
	geoIdFunction: function (obj) {
		switch (obj.Raum.length) {
			case 9:
				return '0'+obj.Raum.substr(0,7);
			case 8:
				return obj.Raum;
			case 7:
				return '0'+obj.Raum;
			default:
				console.error('Unknown length: '+obj.Raum.length+' ('+obj.Raum+')');
				return undefined
		}
	},
	geoName: 'Planungsraum'
};

for (var year = 2007; year <= 2009; year++) {
	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Arbeitslose in % der 15-65-Jährigen', valueFunction: function (obj) { return obj['Arbeitslose'] }, minValue:0, maxValue:21
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Arbeitslose unter 25 Jahren in % der 15-25-Jährigen', valueFunction: function (obj) { return obj['Arbeitslose unter 25 Jahren'] }, minValue:0, maxValue:13
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Langzeitarbeitslose', valueFunction: function (obj) { return obj['Langzeitarbeitslose'] }, minValue:0, maxValue:10
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Nichtarbeitslose Empfänger_innen von Existenzsicherungsleistungen', valueFunction: function (obj) { return obj['Nichtarbeitslose Empfaenger'] }, minValue:0, maxValue:40
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Nichterwerbsfähige Empfänger_innen von Existenzsicherungsleistungen unter 15 Jahren', valueFunction: function (obj) { return obj['Nichterwerbsfaehige Empfaenger'] }, minValue:0, maxValue:80
	}));

	gmdb.addData(data, merge(options, { filterFunction: function (obj) { return (obj.Jahr==year) },	year:year,
		tableName:'Kinder und Jugendliche unter 18 Jahren mit Migrationshintergrund', valueFunction: function (obj) { return obj['Migrationshintergrund'] }, minValue:0, maxValue:90
	}));
}

gmdb.addGeo(readGeoJSON('./geo/Planungsraum_25833.geojson').features, {
	geoName: 'Planungsraum',
	geoIdFunction: function (obj) { return obj.SCHLUESSEL },
	synonyms:[
		["12103015","12103115"],
		["12103016","12103116"],
		["12103017","12103117"],
		["12103018","12103218"],
		["12103019","12103219"],
		["12103020","12103220"],
		["12214121","12214421"],
		["12214122","12214422"],
		["12214123","12214423"],
		["12214124","12214424"],
		["12214127","12214527"],
		["12214128","12214528"],
		["12302007","12302107"],
		["12302008","12302108"],
		["12302009","12302109"],
		["12302010","12302110"],
		["12302011","12302211"],
		["12302012","12302212"]
	]
});

gmdb.match();

fs.writeFileSync('../html/data.js', 'var data ='+JSON.stringify(gmdb.exportJSON() /*, null, '\t'*/), 'utf8');

function readCSV(filename, fieldSeparator, valueFields) {
	fieldSeparator = fieldSeparator || ';';
	valueFields = valueFields || [];

	var lines = fs.readFileSync(filename, 'utf8');
	lines = lines.replace(/[\n\r]+/g, '\r');
	lines = lines.replace(new RegExp('\;+\r', 'g'), '\r');
	lines = lines.split('\r');

	var headFields = lines[0].split(fieldSeparator);

	var r = [];
	for (var j = 0; j < headFields.length; j++) {
		var useThis = false;
		for (var k = 0; k < valueFields.length; k++) {
			if (headFields[j].substr(0, valueFields[k].length) == valueFields[k]) useThis = true;
		}
		if (useThis) r.push(headFields[j]);
	};
	valueFields = r;

	var result = [];
	for (var i = 1; i < lines.length; i++) {
		var line = lines[i];
		if (line.length > 0) {
			var fields = line.split(fieldSeparator);
			if (fields.length != headFields.length) console.error('Äääh: "'+line+'"');
			var obj = {};
			for (var j = 0; j < fields.length; j++) obj[headFields[j]] = fields[j];
			for (var j = 0; j < valueFields.length; j++) {
				var s = obj[valueFields[j]];
				s = s.replace(',','.');
				obj[valueFields[j]] = parseFloat(s);
			}
			result.push(obj);
		}
	}
	return result;
}

function readGeoJSON(filename) {
	var json = fs.readFileSync(filename, 'utf8');
	return JSON.parse(json);
}<|endoftext|>


<commit_before>dojo.provide("dijit.Dialog");

dojo.require("dojo.dnd.move");
dojo.require("dojo.fx");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.form.Form");

dojo.declare(
	"dijit.DialogUnderlay",
	[dijit._Widget, dijit._Templated],
	{
		// summary: the thing that grays out the screen behind the dialog

		// Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.
		// Inner div has opacity specified in CSS file.
		templateString: "

",

		postCreate: function(){
			dojo.body().appendChild(this.domNode);
			this.bgIframe = new dijit.BackgroundIframe(this.domNode);
		},

		layout: function(){
			// summary
			//		Sets the background to the size of the viewport (rather than the size
			//		of the document) since we need to cover the whole browser window, even
			//		if the document is only a few lines long.

			var viewport = dijit.getViewport();
			var is = this.node.style,
				os = this.domNode.style;

			os.top = viewport.t + "px";
			os.left = viewport.l + "px";
			is.width = viewport.w + "px";
			is.height = viewport.h + "px";

			// process twice since the scroll bar may have been removed
			// by the previous resizing
			var viewport2 = dijit.getViewport();
			if(viewport.w != viewport2.w){ is.width = viewport2.w + "px"; }
			if(viewport.h != viewport2.h){ is.height = viewport2.h + "px"; }
		},

		show: function(){
			this.domNode.style.display = "block";
			this.layout();
			if(this.bgIframe.iframe){
				this.bgIframe.iframe.style.display = "block";
			}
			this._resizeHandler = this.connect(window, "onresize", "layout");
		},

		hide: function(){
			this.domNode.style.display = "none";
			this.domNode.style.width = this.domNode.style.height = "1px";
			if(this.bgIframe.iframe){
				this.bgIframe.iframe.style.display = "none";
			}
			this.disconnect(this._resizeHandler);
		},

		uninitialize: function(){
			if(this.bgIframe){
				this.bgIframe.destroy();
			}
		}
	}
);

dojo.declare(
	"dijit.Dialog",
	[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],
	{
		// summary:
		//		Pops up a modal dialog window, blocking access to the screen
		//		and also graying out the screen Dialog is extended from
		//		ContentPane so it supports all the same parameters (href, etc.)

		templateString: null,
		templatePath: dojo.moduleUrl("dijit", "templates/Dialog.html"),

		// title: String
		//		Title of the dialog
		title: "",

		duration: 400,

		_lastFocusItem:null,

		postCreate: function(){
			dojo.body().appendChild(this.domNode);
			dijit.Dialog.superclass.postCreate.apply(this, arguments);
			this.domNode.style.display="none";
			this.connect(this, "onExecute", "hide");
			this.connect(this, "onCancel", "hide");
		},

		onLoad: function(){
			// when href is specified we need to reposition
			// the dialog after the data is loaded
			this._position();
			dijit.Dialog.superclass.onLoad.call(this);
		},

		_setup: function(){
			// summary:
			//		stuff we need to do before showing the Dialog for the first
			//		time (but we defer it until right beforehand, for
			//		performance reasons)

			this._modalconnects = [];

			if(this.titleBar){
				this._moveable = new dojo.dnd.Moveable(this.domNode, { handle: this.titleBar });
			}

			this._underlay = new dijit.DialogUnderlay();

			var node = this.domNode;
			this._fadeIn = dojo.fx.combine(
				[dojo.fadeIn({
					node: node,
					duration: this.duration
				 }),
				 dojo.fadeIn({
					node: this._underlay.domNode,
					duration: this.duration,
					onBegin: dojo.hitch(this._underlay, "show")
				 })
				]
			);

			this._fadeOut = dojo.fx.combine(
				[dojo.fadeOut({
					node: node,
					duration: this.duration,
					onEnd: function(){
						node.style.display="none";
					}
				 }),
				 dojo.fadeOut({
					node: this._underlay.domNode,
					duration: this.duration,
					onEnd: dojo.hitch(this._underlay, "hide")
				 })
				]
			);
		},

		uninitialize: function(){
			if(this._underlay){
				this._underlay.destroy();
			}
		},

		_position: function(){
			// summary: position modal dialog in center of screen

			var viewport = dijit.getViewport();
			var mb = dojo.marginBox(this.domNode);

			var style = this.domNode.style;
			style.left = (viewport.l + (viewport.w - mb.w)/2) + "px";
			style.top = (viewport.t + (viewport.h - mb.h)/2) + "px";
		},

		_findLastFocus: function(/*Event*/ evt){
			// summary:  called from onblur of dialog container to determine the last focusable item
			this._lastFocused = evt.target;
		},

		_cycleFocus: function(/*Event*/ evt){
			// summary: when tabEnd receives focus, advance focus around to titleBar

			// on first focus to tabEnd, store the last focused item in dialog
			if(!this._lastFocusItem){
				this._lastFocusItem = this._lastFocused;
			}
			this.titleBar.focus();
		},

		_onKey: function(/*Event*/ evt){
			if(evt.keyCode){
				var node = evt.target;
				// see if we are shift-tabbing from titleBar
				if(node == this.titleBar && evt.shiftKey && evt.keyCode == dojo.keys.TAB){
					if (this._lastFocusItem){
						this._lastFocusItem.focus(); // send focus to last item in dialog if known
					}
					dojo.stopEvent(evt);
				}else{
					// see if the key is for the dialog
					while (node){
						if(node == this.domNode){
							if (evt.keyCode == dojo.keys.ESCAPE){
								this.hide();
							}else{
								return; // just let it go
							}
						}
						node = node.parentNode;
					}
					// this key is for the disabled document window
					if (evt.keyCode != dojo.keys.TAB){ // allow tabbing into the dialog for a11y
						dojo.stopEvent(evt);
					// opera won't tab to a div
					}else if (!dojo.isOpera){
						try{
							this.titleBar.focus();
						}catch(e){/*squelch*/}
					}
				}
			}
		},

		show: function(){
			// summary: display the dialog

			// first time we show the dialog, there's some initialization stuff to do
			if(!this._alreadyInitialized){
				this._setup();
				this._alreadyInitialized=true;
			}

			if(this._fadeOut.status() == "playing"){
				this._fadeOut.stop();
			}

			this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));
			this._modalconnects.push(dojo.connect(document.documentElement, "onkeypress", this, "_onKey"));

			// IE doesn't bubble onblur events - use ondeactivate instead
			var ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";
			this._modalconnects.push(dojo.connect(this.containerNode, ev, this, "_findLastFocus"));

			dojo.style(this.domNode, "opacity", 0);
			this.domNode.style.display="block";

			this._loadCheck(); // lazy load trigger

			this._position();

			this._fadeIn.play();

			this._savedFocus = dijit.getFocus(this);

			// set timeout to allow the browser to render dialog
			setTimeout(dojo.hitch(this, function(){
				dijit.focus(this.titleBar);
			}), 50);
		},

		hide: function(){
			// summary
			//		Hide the dialog

			// if we haven't been initialized yet then we aren't showing and we can just return
			if(!this._alreadyInitialized){
				return;
			}

			if(this._fadeIn.status() == "playing"){
				this._fadeIn.stop();
			}
			this._fadeOut.play();

			if (this._scrollConnected){
				this._scrollConnected = false;
			}
			dojo.forEach(this._modalconnects, dojo.disconnect);
			this._modalconnects = [];

			// TODO: this is failing on FF presumably because the DialogUnderlay hasn't disappeared yet?
			// Attach it to fire at the end of the animation
			dijit.focus(this._savedFocus);
		},

		layout: function() {
			if(this.domNode.style.display == "block"){
				this._underlay.layout();
				this._position();
			}
		}
	}
);

dojo.declare(
	"dijit.TooltipDialog",
	[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],
	{
		// summary:
		//		Pops up a dialog that appears like a Tooltip

		// title: String
		// Description of tooltip dialog (required for a11Y)
		title: "",

		_lastFocusItem: null,

		templateString: null,
		templatePath: dojo.moduleUrl("dijit.layout", "templates/TooltipDialog.html"),

		postCreate: function(){
			dijit.TooltipDialog.superclass.postCreate.apply(this, arguments);
			this.connect(this.containerNode, "onkeypress", "_onKey");

			// IE doesn't bubble onblur events - use ondeactivate instead
			var ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";
			this.connect(this.containerNode, ev, "_findLastFocus");
			this.containerNode.title=this.title;
		},

		orient: function(/*Object*/ corner){
			// summary: configure widget to be displayed in given position relative to the button
			this.domNode.className="dijitTooltipDialog " +" dijitTooltipAB"+(corner.charAt(1)=='L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0)=='T' ? "Below" : "Above");
		},

		onOpen: function(/*Object*/ pos){
			// summary: called when dialog is displayed
			this.orient(pos.corner);
			this._loadCheck(); // lazy load trigger
			this.containerNode.focus();
		},

		_onKey: function(/*Event*/ evt){
			//summary: keep keyboard focus in dialog; close dialog on escape key
			if (evt.keyCode == dojo.keys.ESCAPE){
				this.onCancel();
			}else if (evt.target == this.containerNode && evt.shiftKey && evt.keyCode == dojo.keys.TAB){
				if (this._lastFocusItem){
					this._lastFocusItem.focus();
				}
				dojo.stopEvent(evt);
			}
		},

		_findLastFocus: function(/*Event*/ evt){
			// summary:  called from onblur of dialog container to determine the last focusable item
			this._lastFocused = evt.target;
		},

		_cycleFocus: function(/*Event*/ evt){
			// summary: when tabEnd receives focus, advance focus around to containerNode

			// on first focus to tabEnd, store the last focused item in dialog
			if(!this._lastFocusItem){
				this._lastFocusItem = this._lastFocused;
			}
			this.containerNode.focus();
		}
	}
);

<commit_msg>fixes #4279 - adds open: param/API to Dialog (though does not make start  open, like TitlePane open="true") ... is true when open, false when  hidden. <commit_after>dojo.provide("dijit.Dialog");

dojo.require("dojo.dnd.move");
dojo.require("dojo.fx");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.form.Form");

dojo.declare(
	"dijit.DialogUnderlay",
	[dijit._Widget, dijit._Templated],
	{
		// summary: the thing that grays out the screen behind the dialog

		// Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.
		// Inner div has opacity specified in CSS file.
		templateString: "

",

		postCreate: function(){
			dojo.body().appendChild(this.domNode);
			this.bgIframe = new dijit.BackgroundIframe(this.domNode);
		},

		layout: function(){
			// summary
			//		Sets the background to the size of the viewport (rather than the size
			//		of the document) since we need to cover the whole browser window, even
			//		if the document is only a few lines long.

			var viewport = dijit.getViewport();
			var is = this.node.style,
				os = this.domNode.style;

			os.top = viewport.t + "px";
			os.left = viewport.l + "px";
			is.width = viewport.w + "px";
			is.height = viewport.h + "px";

			// process twice since the scroll bar may have been removed
			// by the previous resizing
			var viewport2 = dijit.getViewport();
			if(viewport.w != viewport2.w){ is.width = viewport2.w + "px"; }
			if(viewport.h != viewport2.h){ is.height = viewport2.h + "px"; }
		},

		show: function(){
			this.domNode.style.display = "block";
			this.layout();
			if(this.bgIframe.iframe){
				this.bgIframe.iframe.style.display = "block";
			}
			this._resizeHandler = this.connect(window, "onresize", "layout");
		},

		hide: function(){
			this.domNode.style.display = "none";
			this.domNode.style.width = this.domNode.style.height = "1px";
			if(this.bgIframe.iframe){
				this.bgIframe.iframe.style.display = "none";
			}
			this.disconnect(this._resizeHandler);
		},

		uninitialize: function(){
			if(this.bgIframe){
				this.bgIframe.destroy();
			}
		}
	}
);

dojo.declare(
	"dijit.Dialog",
	[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],
	{
		// summary:
		//		Pops up a modal dialog window, blocking access to the screen
		//		and also graying out the screen Dialog is extended from
		//		ContentPane so it supports all the same parameters (href, etc.)

		templateString: null,
		templatePath: dojo.moduleUrl("dijit", "templates/Dialog.html"),

		// title: String
		//		Title of the dialog
		title: "",

		// open: Boolean
		//		is True or False depending on state of dialog
		open: false,

		duration: 400,

		_lastFocusItem:null,

		postCreate: function(){
			dojo.body().appendChild(this.domNode);
			dijit.Dialog.superclass.postCreate.apply(this, arguments);
			this.domNode.style.display="none";
			this.connect(this, "onExecute", "hide");
			this.connect(this, "onCancel", "hide");
		},

		onLoad: function(){
			// when href is specified we need to reposition
			// the dialog after the data is loaded
			this._position();
			dijit.Dialog.superclass.onLoad.call(this);
		},

		_setup: function(){
			// summary:
			//		stuff we need to do before showing the Dialog for the first
			//		time (but we defer it until right beforehand, for
			//		performance reasons)

			this._modalconnects = [];

			if(this.titleBar){
				this._moveable = new dojo.dnd.Moveable(this.domNode, { handle: this.titleBar });
			}

			this._underlay = new dijit.DialogUnderlay();

			var node = this.domNode;
			this._fadeIn = dojo.fx.combine(
				[dojo.fadeIn({
					node: node,
					duration: this.duration
				 }),
				 dojo.fadeIn({
					node: this._underlay.domNode,
					duration: this.duration,
					onBegin: dojo.hitch(this._underlay, "show")
				 })
				]
			);

			this._fadeOut = dojo.fx.combine(
				[dojo.fadeOut({
					node: node,
					duration: this.duration,
					onEnd: function(){
						node.style.display="none";
					}
				 }),
				 dojo.fadeOut({
					node: this._underlay.domNode,
					duration: this.duration,
					onEnd: dojo.hitch(this._underlay, "hide")
				 })
				]
			);
		},

		uninitialize: function(){
			if(this._underlay){
				this._underlay.destroy();
			}
		},

		_position: function(){
			// summary: position modal dialog in center of screen

			var viewport = dijit.getViewport();
			var mb = dojo.marginBox(this.domNode);

			var style = this.domNode.style;
			style.left = (viewport.l + (viewport.w - mb.w)/2) + "px";
			style.top = (viewport.t + (viewport.h - mb.h)/2) + "px";
		},

		_findLastFocus: function(/*Event*/ evt){
			// summary:  called from onblur of dialog container to determine the last focusable item
			this._lastFocused = evt.target;
		},

		_cycleFocus: function(/*Event*/ evt){
			// summary: when tabEnd receives focus, advance focus around to titleBar

			// on first focus to tabEnd, store the last focused item in dialog
			if(!this._lastFocusItem){
				this._lastFocusItem = this._lastFocused;
			}
			this.titleBar.focus();
		},

		_onKey: function(/*Event*/ evt){
			if(evt.keyCode){
				var node = evt.target;
				// see if we are shift-tabbing from titleBar
				if(node == this.titleBar && evt.shiftKey && evt.keyCode == dojo.keys.TAB){
					if (this._lastFocusItem){
						this._lastFocusItem.focus(); // send focus to last item in dialog if known
					}
					dojo.stopEvent(evt);
				}else{
					// see if the key is for the dialog
					while (node){
						if(node == this.domNode){
							if (evt.keyCode == dojo.keys.ESCAPE){
								this.hide();
							}else{
								return; // just let it go
							}
						}
						node = node.parentNode;
					}
					// this key is for the disabled document window
					if (evt.keyCode != dojo.keys.TAB){ // allow tabbing into the dialog for a11y
						dojo.stopEvent(evt);
					// opera won't tab to a div
					}else if (!dojo.isOpera){
						try{
							this.titleBar.focus();
						}catch(e){/*squelch*/}
					}
				}
			}
		},

		show: function(){
			// summary: display the dialog

			// first time we show the dialog, there's some initialization stuff to do
			if(!this._alreadyInitialized){
				this._setup();
				this._alreadyInitialized=true;
			}

			if(this._fadeOut.status() == "playing"){
				this._fadeOut.stop();
			}

			this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));
			this._modalconnects.push(dojo.connect(document.documentElement, "onkeypress", this, "_onKey"));

			// IE doesn't bubble onblur events - use ondeactivate instead
			var ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";
			this._modalconnects.push(dojo.connect(this.containerNode, ev, this, "_findLastFocus"));

			dojo.style(this.domNode, "opacity", 0);
			this.domNode.style.display="block";

			this._loadCheck(); // lazy load trigger

			this._position();

			this._fadeIn.play();

			this._savedFocus = dijit.getFocus(this);

			// set timeout to allow the browser to render dialog
			setTimeout(dojo.hitch(this, function(){
				dijit.focus(this.titleBar);
			}), 50);
			this.open = true;
		},

		hide: function(){
			// summary
			//		Hide the dialog

			// if we haven't been initialized yet then we aren't showing and we can just return
			if(!this._alreadyInitialized){
				return;
			}

			if(this._fadeIn.status() == "playing"){
				this._fadeIn.stop();
			}
			this._fadeOut.play();

			if (this._scrollConnected){
				this._scrollConnected = false;
			}
			dojo.forEach(this._modalconnects, dojo.disconnect);
			this._modalconnects = [];

			// TODO: this is failing on FF presumably because the DialogUnderlay hasn't disappeared yet?
			// Attach it to fire at the end of the animation
			dijit.focus(this._savedFocus);
			this.open = false;
		},

		layout: function() {
			if(this.domNode.style.display == "block"){
				this._underlay.layout();
				this._position();
			}
		}
	}
);

dojo.declare(
	"dijit.TooltipDialog",
	[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],
	{
		// summary:
		//		Pops up a dialog that appears like a Tooltip

		// title: String
		// Description of tooltip dialog (required for a11Y)
		title: "",

		_lastFocusItem: null,

		templateString: null,
		templatePath: dojo.moduleUrl("dijit.layout", "templates/TooltipDialog.html"),

		postCreate: function(){
			dijit.TooltipDialog.superclass.postCreate.apply(this, arguments);
			this.connect(this.containerNode, "onkeypress", "_onKey");

			// IE doesn't bubble onblur events - use ondeactivate instead
			var ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";
			this.connect(this.containerNode, ev, "_findLastFocus");
			this.containerNode.title=this.title;
		},

		orient: function(/*Object*/ corner){
			// summary: configure widget to be displayed in given position relative to the button
			this.domNode.className="dijitTooltipDialog " +" dijitTooltipAB"+(corner.charAt(1)=='L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0)=='T' ? "Below" : "Above");
		},

		onOpen: function(/*Object*/ pos){
			// summary: called when dialog is displayed
			this.orient(pos.corner);
			this._loadCheck(); // lazy load trigger
			this.containerNode.focus();
		},

		_onKey: function(/*Event*/ evt){
			//summary: keep keyboard focus in dialog; close dialog on escape key
			if (evt.keyCode == dojo.keys.ESCAPE){
				this.onCancel();
			}else if (evt.target == this.containerNode && evt.shiftKey && evt.keyCode == dojo.keys.TAB){
				if (this._lastFocusItem){
					this._lastFocusItem.focus();
				}
				dojo.stopEvent(evt);
			}
		},

		_findLastFocus: function(/*Event*/ evt){
			// summary:  called from onblur of dialog container to determine the last focusable item
			this._lastFocused = evt.target;
		},

		_cycleFocus: function(/*Event*/ evt){
			// summary: when tabEnd receives focus, advance focus around to containerNode

			// on first focus to tabEnd, store the last focused item in dialog
			if(!this._lastFocusItem){
				this._lastFocusItem = this._lastFocused;
			}
			this.containerNode.focus();
		}
	}
);

<|endoftext|>


<commit_before>var path = require('path');
var snippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;

module.exports = function ( grunt ) {
	var projectName = 'litemq';

	grunt.initConfig({
		jshint: {
			options: {
				jshintrc: '.jshintrc'
			},
      files: ['*.src.js', '*.spec.js']
    },

    uglify: {
      build: {
        src: ['*.src.js'],
        dest: projectName+'.min.js'
      }
    },

		connect: {
			pivotal: {
				options: {
					port: 9001,
					base: '.'
				}
			},

			livereload: {
        options: {
          port: 9001,
          middleware: function(connect, options) {
            return [snippet, connect.static(path.resolve(options.base))];
          }
        }
      }
		},

		livereload: {
      port: 35729
    },

	  jasmine: {
			pivotal: {
				src: '*.src.js',
				options: {
					host: 'http://localhost:9001/',
					vendor: 'lib/o.min.js',
					specs: '*.spec.js',
					outfile: 'runner.html'
				}
			}
		},

		regarde: {
			pivotal: {
				files: ['**/*.src.js', '**/*.spec.js'],
				tasks: ['jasmine:pivotal'],
				spawn: true
			},

      livereload: {
        files: ['**/*.src.js', '**/*.spec.js'],
        tasks: ['livereload']
      }
    }
	});

	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-jasmine');
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-livereload');
	grunt.loadNpmTasks('grunt-regarde');

	// Aliased tasks (for readability purposes on "build" task)
  grunt.registerTask('o:jsmin', 'uglify:build');
  grunt.registerTask('o:jslint', 'jshint');
	grunt.registerTask('o:ci', ['connect:pivotal', 'jasmine']);
	grunt.registerTask('o:regarde:pivotal', ['connect:pivotal', 'regarde:pivotal']);
	grunt.registerTask('o:regarde:livereload', ['livereload-start', 'connect:livereload', 'jasmine:pivotal:build', 'regarde:livereload']);

	// Batch taks
	grunt.registerTask('o:build', ['o:ci', 'o:jslint', 'o:jsmin']);
};
<commit_msg>Grunt: grouping batch tasks<commit_after>var path = require('path');
var snippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;

module.exports = function ( grunt ) {
	var projectName = 'litemq';

	grunt.initConfig({
		jshint: {
			options: {
				jshintrc: '.jshintrc'
			},
      files: ['*.src.js', '*.spec.js']
    },

    uglify: {
      build: {
        src: ['*.src.js'],
        dest: projectName+'.min.js'
      }
    },

		connect: {
			pivotal: {
				options: {
					port: 9001,
					base: '.'
				}
			},

			livereload: {
        options: {
          port: 9001,
          middleware: function(connect, options) {
            return [snippet, connect.static(path.resolve(options.base))];
          }
        }
      }
		},

		livereload: {
      port: 35729
    },

	  jasmine: {
			pivotal: {
				src: '*.src.js',
				options: {
					host: 'http://localhost:9001/',
					vendor: 'lib/o.min.js',
					specs: '*.spec.js',
					outfile: 'runner.html'
				}
			}
		},

		regarde: {
			pivotal: {
				files: ['**/*.src.js', '**/*.spec.js'],
				tasks: ['jasmine:pivotal'],
				spawn: true
			},

      livereload: {
        files: ['**/*.src.js', '**/*.spec.js'],
        tasks: ['livereload']
      }
    }
	});

	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-jasmine');
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-livereload');
	grunt.loadNpmTasks('grunt-regarde');

	// Aliased tasks (for readability purposes on "build" task)
  grunt.registerTask('o:jsmin', 'uglify:build');
  grunt.registerTask('o:jslint', 'jshint');

	// Batch taks
	grunt.registerTask('o:ci', ['connect:pivotal', 'jasmine']);
	grunt.registerTask('o:pivotal', ['connect:pivotal', 'regarde:pivotal']);
	grunt.registerTask('o:livereload', ['livereload-start', 'connect:livereload', 'jasmine:pivotal:build', 'regarde:livereload']);
	grunt.registerTask('o:build', ['o:ci', 'o:jslint', 'o:jsmin']);
};
<|endoftext|>