<commit_before>/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * 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';

process.env.DEBUG = 'actions-on-google:*';

const Assistant = require('actions-on-google').ApiAiAssistant;
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const know = admin.database().ref('/animal-knowledge');
const graph = know.child('graph');

// API.AI Intent names
const PLAY_INTENT = 'play';
const NO_INTENT = 'discriminate-no';
const YES_INTENT = 'discriminate-yes';
const GIVEUP_INTENT = 'give-up';
const LEARN_THING_INTENT = 'learn-thing';
const LEARN_DISCRIM_INTENT = 'learn-discrimination';

// Contexts
const WELCOME_CONTEXT = 'welcome';
const QUESTION_CONTEXT = 'question';
const GUESS_CONTEXT = 'guess';
const LEARN_THING_CONTEXT = 'learn-thing';
const LEARN_DISCRIM_CONTEXT = 'learn-discrimination';
const ANSWER_CONTEXT = 'answer';

// Context Parameters
const ID_PARAM = 'id';
const BRANCH_PARAM = 'branch';
const LEARN_THING_PARAM = 'learn-thing';
const GUESSABLE_THING_PARAM = 'guessable-thing';
const LEARN_DISCRIMINATION_PARAM = 'learn-discrimination';
const ANSWER_PARAM = 'answer';
const QUESTION_PARAM = 'question';

exports.assistantcodelab = functions.https.onRequest((request, response) => {
    console.log('headers: ' + JSON.stringify(request.headers));
    console.log('body: ' + JSON.stringify(request.body));

    const assistant = new Assistant({request: request, response: response});

    let actionMap = new Map();
    actionMap.set(PLAY_INTENT, play);
    actionMap.set(NO_INTENT, discriminate);
    actionMap.set(YES_INTENT, discriminate);
    actionMap.set(GIVEUP_INTENT, giveUp);
    actionMap.set(LEARN_THING_INTENT, learnThing);
    actionMap.set(LEARN_DISCRIM_INTENT, learnDiscrimination);
    assistant.handleRequest(actionMap);

    function play(assistant) {
        console.log('play');
        const first_ref = know.child('first');
        first_ref.once('value', snap => {
            const first = snap.val();
            console.log(`First: ${first}`);
            graph.child(first).once('value', snap => {
                const speech = `<speak>
Great! Think of an animal, but don't tell me what it is yet. <break time="3"/>
Okay, my first question is: ${snap.val().q}
</speak>`;

                const parameters = {};
                parameters[ID_PARAM] = snap.key;
                assistant.setContext(QUESTION_CONTEXT, 5, parameters);
                assistant.ask(speech);
            });
        });
    }

    function discriminate(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;

        const intent = assistant.getIntent();
        let yes_no;
        if (YES_INTENT === intent) {
            yes_no = 'y';
        } else {
            yes_no = 'n';
        }

        console.log(`prior question: ${priorQuestion}`);

        graph.child(priorQuestion).once('value', snap => {
            const next = snap.val()[yes_no];
            graph.child(next).once('value', snap => {
                const node = snap.val();
                if (node.q) {
                    const speech = node.q;

                    const parameters = {};
                    parameters[ID_PARAM] = snap.key;
                    assistant.setContext(QUESTION_CONTEXT, 5, parameters);
                    assistant.ask(speech);
                } else {
                    const guess = node.a;
                    const speech = `Is it a ${guess}?`;

                    const parameters = {};
                    parameters[ID_PARAM] = snap.key;
                    parameters[BRANCH_PARAM] = yes_no;
                    assistant.setContext(GUESS_CONTEXT, 5, parameters);
                    assistant.ask(speech);
                }
            });
        });
    }

    function giveUp(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;
        const guess = assistant.getContextArgument(GUESS_CONTEXT, ID_PARAM).value;
        console.log(`Priorq: ${priorQuestion}, guess: ${guess}`);

        const speech = 'I give up!  What are you thinking of?';

        const parameters = {};
        parameters[LEARN_THING_PARAM] = true;
        assistant.setContext(LEARN_THING_CONTEXT, 2, parameters);
        assistant.ask(speech);
    }

    function learnThing(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;
        const guess = assistant.getContextArgument(GUESS_CONTEXT, ID_PARAM).value;
        const branch = assistant.getContextArgument(GUESS_CONTEXT, BRANCH_PARAM).value;
        const new_thing = assistant.getArgument(GUESSABLE_THING_PARAM);

        console.log(`Priorq: ${priorQuestion}, guess: ${guess}, branch: ${branch}, thing: ${new_thing}`);

        const q_promise = graph.child(priorQuestion).once('value');
        const g_promise = graph.child(guess).once('value');
        Promise.all([q_promise, g_promise]).then(results => {
            const q_snap = results[0];
            const g_snap = results[1];

            // TODO codelab-1: set the proper contexts to learn the differentiation
            const speech = `I don't know how to tell a ${new_thing} from a ${g_snap.val().a}!`;
            assistant.ask(speech);
        });
    }

    function learnDiscrimination(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;
        const guess = assistant.getContextArgument(GUESS_CONTEXT, ID_PARAM).value;
        const branch = assistant.getContextArgument(GUESS_CONTEXT, BRANCH_PARAM).value;
        const answer =  assistant.getContextArgument(ANSWER_CONTEXT, ANSWER_PARAM).value;
        const question = assistant.getArgument(QUESTION_PARAM);

        console.log(`Priorq: ${priorQuestion}, answer: ${answer}, guess: ${guess}, branch: ${branch}, question: ${question}`);

        const a_node = graph.push({
            a: answer
        });

        const q_node = graph.push({
            q: `${question}?`,
            y: a_node.key,
            n: guess
        });

        let predicate = 'a';
        if (['a','e','i','o','u'].indexOf(answer.charAt(0)) != -1) {
            predicate = 'an';
        }

        const update = {};
        update[branch] = q_node.key;
        graph.child(priorQuestion).update(update).then(() => {
            const speech = `<speak>
OK, thanks for the information! I'll remember to ask "${question}" to see if you're thinking of ${predicate} ${answer}.
<break time="1">
Would you like to play again?
</speak>
`;
            assistant.setContext(WELCOME_CONTEXT, 1);
            assistant.ask(speech);
        });
    }
});<commit_msg>Swap code for a codelab TODO.<commit_after>/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * 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';

process.env.DEBUG = 'actions-on-google:*';

const Assistant = require('actions-on-google').ApiAiAssistant;
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const know = admin.database().ref('/animal-knowledge');
const graph = know.child('graph');

// API.AI Intent names
const PLAY_INTENT = 'play';
const NO_INTENT = 'discriminate-no';
const YES_INTENT = 'discriminate-yes';
const GIVEUP_INTENT = 'give-up';
const LEARN_THING_INTENT = 'learn-thing';
const LEARN_DISCRIM_INTENT = 'learn-discrimination';

// Contexts
const WELCOME_CONTEXT = 'welcome';
const QUESTION_CONTEXT = 'question';
const GUESS_CONTEXT = 'guess';
const LEARN_THING_CONTEXT = 'learn-thing';
const LEARN_DISCRIM_CONTEXT = 'learn-discrimination';
const ANSWER_CONTEXT = 'answer';

// Context Parameters
const ID_PARAM = 'id';
const BRANCH_PARAM = 'branch';
const LEARN_THING_PARAM = 'learn-thing';
const GUESSABLE_THING_PARAM = 'guessable-thing';
const LEARN_DISCRIMINATION_PARAM = 'learn-discrimination';
const ANSWER_PARAM = 'answer';
const QUESTION_PARAM = 'question';

exports.assistantcodelab = functions.https.onRequest((request, response) => {
    console.log('headers: ' + JSON.stringify(request.headers));
    console.log('body: ' + JSON.stringify(request.body));

    const assistant = new Assistant({request: request, response: response});

    let actionMap = new Map();
    actionMap.set(PLAY_INTENT, play);
    actionMap.set(NO_INTENT, discriminate);
    actionMap.set(YES_INTENT, discriminate);
    actionMap.set(GIVEUP_INTENT, giveUp);
    actionMap.set(LEARN_THING_INTENT, learnThing);
    actionMap.set(LEARN_DISCRIM_INTENT, learnDiscrimination);
    assistant.handleRequest(actionMap);

    function play(assistant) {
        console.log('play');
        const first_ref = know.child('first');
        first_ref.once('value', snap => {
            const first = snap.val();
            console.log(`First: ${first}`);
            graph.child(first).once('value', snap => {
                const speech = `<speak>
Great! Think of an animal, but don't tell me what it is yet. <break time="3"/>
Okay, my first question is: ${snap.val().q}
</speak>`;

                const parameters = {};
                parameters[ID_PARAM] = snap.key;
                assistant.setContext(QUESTION_CONTEXT, 5, parameters);
                assistant.ask(speech);
            });
        });
    }

    function discriminate(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;

        const intent = assistant.getIntent();
        let yes_no;
        if (YES_INTENT === intent) {
            yes_no = 'y';
        } else {
            yes_no = 'n';
        }

        console.log(`prior question: ${priorQuestion}`);

        graph.child(priorQuestion).once('value', snap => {
            const next = snap.val()[yes_no];
            graph.child(next).once('value', snap => {
                const node = snap.val();
                if (node.q) {
                    const speech = node.q;

                    const parameters = {};
                    parameters[ID_PARAM] = snap.key;
                    assistant.setContext(QUESTION_CONTEXT, 5, parameters);
                    assistant.ask(speech);
                } else {
                    const guess = node.a;
                    const speech = `Is it a ${guess}?`;

                    const parameters = {};
                    parameters[ID_PARAM] = snap.key;
                    parameters[BRANCH_PARAM] = yes_no;
                    assistant.setContext(GUESS_CONTEXT, 5, parameters);
                    assistant.ask(speech);
                }
            });
        });
    }

    function giveUp(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;
        const guess = assistant.getContextArgument(GUESS_CONTEXT, ID_PARAM).value;
        console.log(`Priorq: ${priorQuestion}, guess: ${guess}`);

        const speech = 'I give up!  What are you thinking of?';

        const parameters = {};
        parameters[LEARN_THING_PARAM] = true;
        assistant.setContext(LEARN_THING_CONTEXT, 2, parameters);
        assistant.ask(speech);
    }

    function learnThing(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;
        const guess = assistant.getContextArgument(GUESS_CONTEXT, ID_PARAM).value;
        const branch = assistant.getContextArgument(GUESS_CONTEXT, BRANCH_PARAM).value;
        const new_thing = assistant.getArgument(GUESSABLE_THING_PARAM);

        console.log(`Priorq: ${priorQuestion}, guess: ${guess}, branch: ${branch}, thing: ${new_thing}`);

        const q_promise = graph.child(priorQuestion).once('value');
        const g_promise = graph.child(guess).once('value');
        Promise.all([q_promise, g_promise]).then(results => {
            const q_snap = results[0];
            const g_snap = results[1];

            // TODO codelab-1: set the proper contexts to learn the differentiation
            const speech = `I don't know how to tell a ${new_thing} from a ${g_snap.val().a}!`;
            assistant.ask(speech);
        });
    }

    function learnDiscrimination(assistant) {
        const priorQuestion = assistant.getContextArgument(QUESTION_CONTEXT, ID_PARAM).value;
        const guess = assistant.getContextArgument(GUESS_CONTEXT, ID_PARAM).value;
        const branch = assistant.getContextArgument(GUESS_CONTEXT, BRANCH_PARAM).value;
        const answer =  assistant.getContextArgument(ANSWER_CONTEXT, ANSWER_PARAM).value;
        const question = assistant.getArgument(QUESTION_PARAM);

        console.log(`Priorq: ${priorQuestion}, answer: ${answer}, guess: ${guess}, branch: ${branch}, question: ${question}`);

        const a_node = graph.push({
            a: answer
        });

        const q_node = graph.push({
            q: `${question}?`,
            y: a_node.key,
            n: guess
        });

        let predicate = 'a';
        if (['a','e','i','o','u'].indexOf(answer.charAt(0)) != -1) {
            predicate = 'an';
        }

        const update = {};
        update[branch] = q_node.key;
        graph.child(priorQuestion).update(update).then(() => {
            // TODO codelab-2: give the user an option to play again or end the conversation
            const speech = "Ok, thanks for the information!";
            assistant.ask(speech);
        });
    }
});<|endoftext|>


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

  var mod = angular.module('ng-current', [])

  /**
   * Establishes a relational context that delegates
   * updates (from top to bottom) according to PubSub
   */
  mod.service('Contexts', ['$log', '$rootScope', '$q', function($log, $rootScope, $q) {
    var self = this

    /**
     * Tracks all context relations
     */
    this.contexts = {}

    /**
     * Stores current active state for each registered context (by rel)
     */
    $rootScope.current = {}

    /**
     * Registers a service as a context and subscribes the provided
     * service's model to its own changes
     *
     * @param {Object} service typically `this` of the service
     */
    this.register = function(service) {
      this.contexts[service.name] = service.rels || []

      service.refresh = self.refreshing(service)
      service.use     = self.using(service)

      service.constructor.prototype = this.constructor.prototype

      $rootScope.current[name] = {}
    }

    /**
     * Creates a generator that allows users to provide
     * a binding function that reacts to a single Service's
     * changes (in other words, lazy functionality or data
     * that needs to re-process when data changes).
     *
     * @param {Service} angular service
     * @returns {Function} instance refresher accepting an own property to react to (method) and a callback (andThen)
     */
    this.refreshing = function(service) {
      return function(method, andThen) {
        var generator = service[method]
        var model     = service.model || function(data) { return data }

        if (generator instanceof Function) {
          generator().then(function(data) {
            andThen(
              data instanceof Array ? data.map(service.model) : service.model(data)
            )
          })
        } else {
          $log.error('[ng-current.refreshing] failed to find method on service', method)
        }
      }
    }

    /**
     * Creates an integration point where changes to the Service
     * are subscribed to and published hierarchically (single direction, down)
     * to any child Services. Nested publications occur transparently in their
     * own respective Services and are not invoked here.
     *
     * Generally used for subscribing and synchronizing your scope bindings to changes
     * that occur in the appropriate Service context tree/sub-tree (single direction, down).
     *
     * @param {Service} service angular service
     * @returns {Function} usage point accepting an own property to react to (method) and a callback (andThen)
     */
    this.using = function(service) {
      return function(method, andThen) {
        // invoke refresh immediately and then ensure that provided
        // method is subscribed and refreshed w/ future updates to the service
        if (service.constructor.prototype === this.constructor.prototype) {
          service.refresh(method, andThen)

          self.subscribe(service.name, function(data) {
            service.refresh(method, andThen)

            // delegate subscribed changes to immediate related contexts (shallow)
            if (service.rels && service.rels.length) {
              service.rels.forEach(function(rel) {
                self.publish(rel, data)
              })
            }
          })
        } else {
          $log.error('[ng-current.using] malformed Service context, please ensure you have added `Contexts.register(this)` at the end of this service', service)
        }
      }
    }

    /**
     * Clears out a context's current state and then traverses its
     * relationships recursively until all dependent states have
     * been cleared as well.
     *
     * @param {String} name service name
     */
    this.clear = function(name) {
      (self.contexts[name] || []).forEach(function(rel) {
        delete $rootScope.current[rel]

        var next = self.contexts[rel]

        if (next instanceof Array && next.length) {
          next.forEach(self.clear)
        }
      })
    }

    /**
     * Establishes a new current context for
     * a service by name/rel and publishes event
     *
     * @param {String} name service name
     * @param {Object} object to use as representation of current state
     */
    this.select = function(name, data) {
      var old = $rootScope.current[name]

      // only publish update if the current value has changed
      if (!angular.equals(data, old)) {
        $rootScope.current[name] = data

        // ensure all related (and stale) rel contexts are
        // cleared when this a new context becomes current
        self.clear(name)

        // notify related contexts about your new state
        self.publish(name, data)
      }

      return data
    }

    /**
     * Determines which object is currently used for the current Service context
     *
     * @param {String} name service name
     * @returns {Object} currently current state representation of the service
     */
    this.current = function(name) {
      return $rootScope.current[name]
    }

    /**
     * Utility function that provides either the current context (by name)
     * or, if the context has not been established yet, the `none` object.
     *
     * @param {String} name service name
     * @param {Object} none object to use as initial context when none exists yet
     * @returns {Object} current service context or `none` if it doesn't exist
     */
    this.currentOr = function(name, none) {
      var current = this.current(name)

      // provide "none" object when no current context exists yet
      if (!angular.isObject(current) && !angular.isUndefined(none)) {
        return none
      }

      return current
    }

    /**
     * Simple succinct aliases for getting current contexts
     */
    this.get   = self.current
    this.getOr = self.currentOr

    /**
     * Subscribes to a specific relation, performing
     * the user provided behavior whenever a related
     * publication occurs
     *
     * @param {String} rel relation to subscribe to
     * @param {Function} on behavior to invoke on publication
     * @returns {Promise}
     */
    this.subscribe = function(rel, on) {
      return $q(function(resolve, reject) {
        $rootScope.$on(rel, function(event, data) {
          resolve(
            on(data || {}, event)
          )
        })
      })
    }

    /**
     * Publishes data to a service by its registered "rel".
     * If the service has any "rels", publish to those as well.
     * This process does not repeat (shallow)
     *
     * @param {String} rel the relation
     * @param {Object} data
     */
    this.publish = function(rel, data) {
      var rels = self.contexts[rel]                // related services to publish to next
      var pubs = rels ? [rel].concat(rels) : [rel] // complete set of services to publish to

      // broadcast data by traversing (top to bottom) shallow heirarchy
      // of directly related contexts (only 1 level deep)
      pubs.forEach(function(pub) {
        if (pub.constructor === String) {
          $rootScope.$broadcast(pub, data)
        } else {
          throw 'rels must be Strings'
        }
      })

      return data
    }
  }])
})(angular)

if (module && exports && module.exports === exports) {
  module.exports = 'ng-current'
}
<commit_msg>:bug: call user generator method with proper this arg. also updated registration check<commit_after>;(function(angular) {
  'use strict'

  var mod = angular.module('ng-current', [])

  /**
   * Establishes a relational context that delegates
   * updates (from top to bottom) according to PubSub
   */
  mod.service('Contexts', ['$log', '$rootScope', '$q', function($log, $rootScope, $q) {
    var self = this

    /**
     * Tracks all context relations
     */
    this.contexts = {}

    /**
     * Stores current active state for each registered context (by rel)
     */
    $rootScope.current = {}

    /**
     * Registers a service as a context and subscribes the provided
     * service's model to its own changes
     *
     * @param {Object} service typically `this` of the service
     */
    this.register = function(service) {
      this.contexts[service.name] = service.rels || []

      service.refresh = self.refreshing(service)
      service.use     = self.using(service)

      service.$$hasContext = true

      $rootScope.current[name] = {}
    }

    /**
     * Creates a generator that allows users to provide
     * a binding function that reacts to a single Service's
     * changes (in other words, lazy functionality or data
     * that needs to re-process when data changes).
     *
     * @param {Service} angular service
     * @returns {Function} instance refresher accepting an own property to react to (method) and a callback (andThen)
     */
    this.refreshing = function(service) {
      return function(method, andThen) {
        var generator = service[method]
        var model     = service.model || function(data) { return data }

        if (generator instanceof Function) {
          generator.call(service).then(function(data) {
            andThen(
              data instanceof Array ? data.map(service.model) : service.model(data)
            )
          })
        } else {
          $log.error('[ng-current.refreshing] failed to find method on service', method)
        }
      }
    }

    /**
     * Creates an integration point where changes to the Service
     * are subscribed to and published hierarchically (single direction, down)
     * to any child Services. Nested publications occur transparently in their
     * own respective Services and are not invoked here.
     *
     * Generally used for subscribing and synchronizing your scope bindings to changes
     * that occur in the appropriate Service context tree/sub-tree (single direction, down).
     *
     * @param {Service} service angular service
     * @returns {Function} usage point accepting an own property to react to (method) and a callback (andThen)
     */
    this.using = function(service) {
      return function(method, andThen) {
        // invoke refresh immediately and then ensure that provided
        // method is subscribed and refreshed w/ future updates to the service
        if (service.$$hasContext) {
          service.refresh(method, andThen)

          self.subscribe(service.name, function(data) {
            service.refresh(method, andThen)

            // delegate subscribed changes to immediate related contexts (shallow)
            if (service.rels && service.rels.length) {
              service.rels.forEach(function(rel) {
                self.publish(rel, data)
              })
            }
          })
        } else {
          $log.error('[ng-current.using] malformed Service context, please ensure you have added `Contexts.register(this)` at the end of this service', service)
        }
      }
    }

    /**
     * Clears out a context's current state and then traverses its
     * relationships recursively until all dependent states have
     * been cleared as well.
     *
     * @param {String} name service name
     */
    this.clear = function(name) {
      (self.contexts[name] || []).forEach(function(rel) {
        delete $rootScope.current[rel]

        var next = self.contexts[rel]

        if (next instanceof Array && next.length) {
          next.forEach(self.clear)
        }
      })
    }

    /**
     * Establishes a new current context for
     * a service by name/rel and publishes event
     *
     * @param {String} name service name
     * @param {Object} object to use as representation of current state
     */
    this.select = function(name, data) {
      var old = $rootScope.current[name]

      // only publish update if the current value has changed
      if (!angular.equals(data, old)) {
        $rootScope.current[name] = data

        // ensure all related (and stale) rel contexts are
        // cleared when this a new context becomes current
        self.clear(name)

        // notify related contexts about your new state
        self.publish(name, data)
      }

      return data
    }

    /**
     * Determines which object is currently used for the current Service context
     *
     * @param {String} name service name
     * @returns {Object} currently current state representation of the service
     */
    this.current = function(name) {
      return $rootScope.current[name]
    }

    /**
     * Utility function that provides either the current context (by name)
     * or, if the context has not been established yet, the `none` object.
     *
     * @param {String} name service name
     * @param {Object} none object to use as initial context when none exists yet
     * @returns {Object} current service context or `none` if it doesn't exist
     */
    this.currentOr = function(name, none) {
      var current = this.current(name)

      // provide "none" object when no current context exists yet
      if (!angular.isObject(current) && !angular.isUndefined(none)) {
        return none
      }

      return current
    }

    /**
     * Simple succinct aliases for getting current contexts
     */
    this.get   = self.current
    this.getOr = self.currentOr

    /**
     * Subscribes to a specific relation, performing
     * the user provided behavior whenever a related
     * publication occurs
     *
     * @param {String} rel relation to subscribe to
     * @param {Function} on behavior to invoke on publication
     * @returns {Promise}
     */
    this.subscribe = function(rel, on) {
      return $q(function(resolve, reject) {
        $rootScope.$on(rel, function(event, data) {
          resolve(
            on(data || {}, event)
          )
        })
      })
    }

    /**
     * Publishes data to a service by its registered "rel".
     * If the service has any "rels", publish to those as well.
     * This process does not repeat (shallow)
     *
     * @param {String} rel the relation
     * @param {Object} data
     */
    this.publish = function(rel, data) {
      var rels = self.contexts[rel]                // related services to publish to next
      var pubs = rels ? [rel].concat(rels) : [rel] // complete set of services to publish to

      // broadcast data by traversing (top to bottom) shallow heirarchy
      // of directly related contexts (only 1 level deep)
      pubs.forEach(function(pub) {
        if (pub.constructor === String) {
          $rootScope.$broadcast(pub, data)
        } else {
          throw 'rels must be Strings'
        }
      })

      return data
    }
  }])
})(angular)

if (module && exports && module.exports === exports) {
  module.exports = 'ng-current'
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
(function() {
  "use strict";

  // The chunk size of tailing the files, i.e., how many bytes will be shown
  // in the preview.
  var TAIL_CHUNK_SIZE = 32768;
  var helpers = {
    'helper_to_permission': function(chunk, ctx, bodies, params) {
      var p = ctx.current().permission;
      var dir = ctx.current().type == 'DIRECTORY' ? 'd' : '-';
      var symbols = [ '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ];
      var sticky = p > 1000;

      var res = "";
      for (var i = 0; i < 3; ++i) {
	res = symbols[(p % 10)] + res;
	p = Math.floor(p / 10);
      }

      if (sticky) {
      	var otherExec = ((ctx.current().permission % 10) & 1) == 1;
        res = res.substr(0, res.length - 1) + (otherExec ? 't' : 'T');
      }

      chunk.write(dir + res);
      return chunk;
    }
  };

  var base = dust.makeBase(helpers);
  var current_directory = "";

  function show_err_msg(msg) {
    $('#alert-panel-body').html(msg);
    $('#alert-panel').show();
  }

  $(window).bind('hashchange', function () {
    $('#alert-panel').hide();

    var dir = window.location.hash.slice(1);
    if(dir == "") {
      dir = "/";
    }
    if(current_directory != dir) {
      browse_directory(dir);
    }
  });

  function network_error_handler(url) {
    return function (jqxhr, text, err) {
      var msg = '
Failed to retreive data from ' + url + ', cause: ' + err + '
';
      if (url.indexOf('/webhdfs/v1') === 0)  {
        msg += '
WebHDFS might be disabled. WebHDFS is required to browse the filesystem.
';
      }
      show_err_msg(msg);
    };
  }

  function append_path(prefix, s) {
    var l = prefix.length;
    var p = l > 0 && prefix[l - 1] == '/' ? prefix.substring(0, l - 1) : prefix;
    return p + '/' + s;
  }

  function get_response(data, type) {
    return data[type] !== undefined ? data[type] : null;
  }

  function get_response_err_msg(data) {
    var msg = data.RemoteException !== undefined ? data.RemoteException.message : "";
    return msg;
  }

  function view_file_details(path, abs_path) {
    function show_block_info(blocks) {
      var menus = $('#file-info-blockinfo-list');
      menus.empty();

      menus.data("blocks", blocks);
      menus.change(function() {
        var d = $(this).data('blocks')[$(this).val()];
        if (d === undefined) {
          return;
        }

        dust.render('block-info', d, function(err, out) {
          $('#file-info-blockinfo-body').html(out);
        });

      });
      for (var i = 0; i < blocks.length; ++i) {
        var item = $('<option value="' + i + '">Block ' + i + '</option>');
        menus.append(item);
      }
      menus.change();
    }

    var url = '/webhdfs/v1' + abs_path + '?op=GET_BLOCK_LOCATIONS';
    $.ajax({"url": url, "crossDomain": true}).done(function(data) {
      var d = get_response(data, "LocatedBlocks");
      if (d === null) {
        show_err_msg(get_response_err_msg(data));
        return;
      }

      $('#file-info-tail').hide();
      $('#file-info-title').text("File information - " + path);

      var download_url = get_location() + '/webhdfs/v1' + abs_path + '/?op=OPEN';

      $('#file-info-download').attr('href', download_url);
      $('#file-info-preview').click(function() {
        var offset = d.fileLength - TAIL_CHUNK_SIZE;
        var url = offset > 0 ? download_url + '&offset=' + offset : download_url;
        $.get(url, function(t) {
          $('#file-info-preview-body').val(t);
          $('#file-info-tail').show();
        }, "text").error(network_error_handler(url));
      });

      if (d.fileLength > 0) {
        show_block_info(d.locatedBlocks);
        $('#file-info-blockinfo-panel').show();
      } else {
        $('#file-info-blockinfo-panel').hide();
      }
      $('#file-info').modal();
    }).error(network_error_handler(url));
  }

  function browse_directory(dir) {
    var url = get_location() + '/webhdfs/v1' + dir + '?op=LISTSTATUS';
    $.get(url, function(data) {
      var d = get_response(data, "FileStatuses");
      if (d === null) {
        show_err_msg(get_response_err_msg(data));
        return;
      }

      current_directory = dir;
      $('#directory').val(dir);
      dust.render('explorer', base.push(d), function(err, out) {
        $('#panel').html(out);

        $('.explorer-browse-links').click(function() {
          var type = $(this).attr('inode-type');
          var path = $(this).attr('inode-path');
          var abs_path = append_path(current_directory, path);
          if (type == 'DIRECTORY') {
            browse_directory(abs_path);
          } else {
            view_file_details(path, abs_path);
          }
        });
      });
    }).error(network_error_handler(url));
  }

  function init() {
    dust.loadSource(dust.compile($('#tmpl-explorer').html(), 'explorer'));
    dust.loadSource(dust.compile($('#tmpl-block-info').html(), 'block-info'));

    var b = function() { browse_directory($('#directory').val()); };
    $('#btn-nav-directory').click(b);
    var dir = window.location.hash.slice(1);
    if(dir == "") {
      window.location.hash = "/";
    } else {
      browse_directory(dir);
    }
  }

  init();
})();
<commit_msg>[HOPS-519] apply HDFS-5949<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
(function() {
  "use strict";

  // The chunk size of tailing the files, i.e., how many bytes will be shown
  // in the preview.
  var TAIL_CHUNK_SIZE = 32768;
  var helpers = {
    'helper_to_permission': function(chunk, ctx, bodies, params) {
      var p = ctx.current().permission;
      var dir = ctx.current().type == 'DIRECTORY' ? 'd' : '-';
      var symbols = [ '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' ];
      var sticky = p > 1000;

      var res = "";
      for (var i = 0; i < 3; ++i) {
	res = symbols[(p % 10)] + res;
	p = Math.floor(p / 10);
      }

      if (sticky) {
      	var otherExec = ((ctx.current().permission % 10) & 1) == 1;
        res = res.substr(0, res.length - 1) + (otherExec ? 't' : 'T');
      }

      chunk.write(dir + res);
      return chunk;
    }
  };

  var base = dust.makeBase(helpers);
  var current_directory = "";

  function show_err_msg(msg) {
    $('#alert-panel-body').html(msg);
    $('#alert-panel').show();
  }

  $(window).bind('hashchange', function () {
    $('#alert-panel').hide();

    var dir = window.location.hash.slice(1);
    if(dir == "") {
      dir = "/";
    }
    if(current_directory != dir) {
      browse_directory(dir);
    }
  });

  function network_error_handler(url) {
    return function (jqxhr, text, err) {
      var msg = '
Failed to retreive data from ' + url + ', cause: ' + err + '
';
      if (url.indexOf('/webhdfs/v1') === 0)  {
        msg += '
WebHDFS might be disabled. WebHDFS is required to browse the filesystem.
';
      }
      show_err_msg(msg);
    };
  }

  function append_path(prefix, s) {
    var l = prefix.length;
    var p = l > 0 && prefix[l - 1] == '/' ? prefix.substring(0, l - 1) : prefix;
    return p + '/' + s;
  }

  function get_response(data, type) {
    return data[type] !== undefined ? data[type] : null;
  }

  function get_response_err_msg(data) {
    var msg = data.RemoteException !== undefined ? data.RemoteException.message : "";
    return msg;
  }

  function view_file_details(path, abs_path) {
    function show_block_info(blocks) {
      var menus = $('#file-info-blockinfo-list');
      menus.empty();

      menus.data("blocks", blocks);
      menus.change(function() {
        var d = $(this).data('blocks')[$(this).val()];
        if (d === undefined) {
          return;
        }

        dust.render('block-info', d, function(err, out) {
          $('#file-info-blockinfo-body').html(out);
        });

      });
      for (var i = 0; i < blocks.length; ++i) {
        var item = $('<option value="' + i + '">Block ' + i + '</option>');
        menus.append(item);
      }
      menus.change();
    }

    var url = '/webhdfs/v1' + abs_path + '?op=GET_BLOCK_LOCATIONS';
    $.ajax({"url": url, "crossDomain": true}).done(function(data) {
      var d = get_response(data, "LocatedBlocks");
      if (d === null) {
        show_err_msg(get_response_err_msg(data));
        return;
      }

      $('#file-info-tail').hide();
      $('#file-info-title').text("File information - " + path);

      var download_url = get_location() + '/webhdfs/v1' + abs_path + '?op=OPEN';

      $('#file-info-download').attr('href', download_url);
      $('#file-info-preview').click(function() {
        var offset = d.fileLength - TAIL_CHUNK_SIZE;
        var url = offset > 0 ? download_url + '&offset=' + offset : download_url;
        $.get(url, function(t) {
          $('#file-info-preview-body').val(t);
          $('#file-info-tail').show();
        }, "text").error(network_error_handler(url));
      });

      if (d.fileLength > 0) {
        show_block_info(d.locatedBlocks);
        $('#file-info-blockinfo-panel').show();
      } else {
        $('#file-info-blockinfo-panel').hide();
      }
      $('#file-info').modal();
    }).error(network_error_handler(url));
  }

  function browse_directory(dir) {
    var url = get_location() + '/webhdfs/v1' + dir + '?op=LISTSTATUS';
    $.get(url, function(data) {
      var d = get_response(data, "FileStatuses");
      if (d === null) {
        show_err_msg(get_response_err_msg(data));
        return;
      }

      current_directory = dir;
      $('#directory').val(dir);
      dust.render('explorer', base.push(d), function(err, out) {
        $('#panel').html(out);

        $('.explorer-browse-links').click(function() {
          var type = $(this).attr('inode-type');
          var path = $(this).attr('inode-path');
          var abs_path = append_path(current_directory, path);
          if (type == 'DIRECTORY') {
            browse_directory(abs_path);
          } else {
            view_file_details(path, abs_path);
          }
        });
      });
    }).error(network_error_handler(url));
  }

  function init() {
    dust.loadSource(dust.compile($('#tmpl-explorer').html(), 'explorer'));
    dust.loadSource(dust.compile($('#tmpl-block-info').html(), 'block-info'));

    var b = function() { browse_directory($('#directory').val()); };
    $('#btn-nav-directory').click(b);
    var dir = window.location.hash.slice(1);
    if(dir == "") {
      window.location.hash = "/";
    } else {
      browse_directory(dir);
    }
  }

  init();
})();
<|endoftext|>


<commit_before>
var Strukturas = [
    {
        id: "vienkars_saraksts",
        nosaukums: "Vienkāršsaistīts saraksts",
        izveidot: null
    },
    {
        id: "divkars_saraksts",
        nosaukums: "Divkāršsaistīts saraksts",
        izveidot: null
    },
    {
        id: "steks",
        nosaukums: "Steks",
        izveidot: null
    },
    {
        id: "rinda",
        nosaukums: "Rinda",
        izveidot: null
    },
    {
        id: "kaudze",
        nosaukums: "Kaudze",
        izveidot: null
    },
    {
        id: "binars_koks",
        nosaukums: "Binārs koks",
        izveidot: null
    },
    {
        id: "avl_koks",
        nosaukums: "AVL koks",
        izveidot: null
    },
    {
        id: "meklesanas_koks",
        nosaukums: "Meklēšanas koks",
        izveidot: null
    }
];

var c = 0;

function dabutVertibu() {
    return Math.round(Math.random() * 99);
}

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
        this.nakosais = null;
    };
    this.katramElementam = function(fn) {
        var elem = objekts.struktura;
        fn(elem);
        while (elem.nakosais) {
            elem = elem.nakosais;
            fn(elem);
        }
    };
    this.iegutElementu = function(sakuma) {
        if (sakuma) {
            return objekts.struktura;
        } else {
            var elem = objekts.struktura;
            while (elem.nakosais) {
                elem = elem.nakosais;
            }
            return elem;
        }
    };
    this.pievienot = function(vertiba, sakuma) {
        if (objekts.struktura) {
            var elem = objekts.iegutElementu(sakuma);
            elem.nakosais = new objekts.elements(vertiba);
        } else {
            objekts.struktura = new objekts.elements(vertiba);
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        var i = 0;
        objekts.katramElementam(function(elem) {
            i++;
            ramis.left = 50 + (ramis.width + 20) * i;
            teksts.setText(elem.vertiba.toString());
            teksts.left = ramis.left + (ramis.width / 4);
            attels.add(ramis);
            attels.add(teksts);
            elem.zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        });
        objekts.katramElementam(function(elem) {
            if (elem.nakosais) {
                linija.set({x1: elem.zimejums[0].left + elem.zimejums[0].width / 4 * 3,
                            x2: elem.zimejums[0].left + elem.zimejums[0].width + 40,
                            y1: elem.zimejums[0].top + elem.zimejums[0].height / 5,
                            y2: elem.zimejums[0].top + elem.zimejums[0].height / 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'x1': linija.x2 - 15, 'y1': linija.y1 - 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'y1': linija.y1 + 10});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
            }
        });
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
        this.ieprieksejais = null;
        this.nakosais = null;
    };
    this.katramElementam = function(fn) {
        var elem = objekts.struktura;
        fn(elem);
        while (elem.nakosais) {
            elem = elem.nakosais;
            fn(elem);
        }
    };
    this.iegutElementu = function(sakuma) {
        if (sakuma) {
            return objekts.struktura;
        } else {
            var elem = objekts.struktura;
            while (elem.nakosais) {
                elem = elem.nakosais;
            }
            return elem;
        }
    };
    this.pievienot = function(vertiba, sakuma) {
        if (objekts.struktura) {
            var elem = objekts.iegutElementu(sakuma);
            elem.nakosais = new objekts.elements(vertiba);
            elem.nakosais.ieprieksejais = elem;
        } else {
            objekts.struktura = new objekts.elements(vertiba);
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        var i = 0;
        objekts.katramElementam(function(elem) {
            i++;
            ramis.left = 50 + (ramis.width + 20) * i;
            teksts.setText(elem.vertiba.toString());
            teksts.left = ramis.left + (ramis.width / 4);
            attels.add(ramis);
            attels.add(teksts);
            elem.zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        });
        objekts.katramElementam(function(elem) {
            if (elem.nakosais) {
                linija.set({x1: elem.zimejums[0].left + elem.zimejums[0].width / 4 * 3,
                            x2: elem.zimejums[0].left + elem.zimejums[0].width + 40,
                            y1: elem.zimejums[0].top + elem.zimejums[0].height / 5,
                            y2: elem.zimejums[0].top + elem.zimejums[0].height / 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'x1': linija.x2 - 15, 'y1': linija.y1 - 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'y1': linija.y1 + 10});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
            }
            if (elem.ieprieksejais) {
            linija.set({x1: elem.zimejums[0].left + elem.zimejums[0].width / 4,
                        x2: elem.zimejums[0].left - 20 - elem.zimejums[0].width / 4,
                        y1: elem.zimejums[0].top + elem.zimejums[0].height - elem.zimejums[0].height / 6,
                        y2: elem.zimejums[0].top + elem.zimejums[0].height - elem.zimejums[0].height / 6});
            attels.add(linija);
            elem.zimejums.push(linija);
            linija = window.fabric.util.object.clone(linija);
            linija.set({x1: elem.zimejums[0].left - 20 - elem.zimejums[0].width / 4 + 15,
                        y1: linija.y1 - 5});
            attels.add(linija);
            elem.zimejums.push(linija);
            linija = window.fabric.util.object.clone(linija);
            linija.set({'y1': linija.y1 + 10});
            attels.add(linija);
            elem.zimejums.push(linija);
            linija = window.fabric.util.object.clone(linija);
            }
        });
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = [];
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
    };
    this.pievienot = function(vertiba, sakuma) {
        if (sakuma) {
            objekts.struktura.unshift(new objekts.elements(vertiba));
        } else {
            objekts.struktura.push(new objekts.elements(vertiba));
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        ramis.left = 200;
        teksts.left = 215;
        for (var i = 0; i < objekts.struktura.length; i++) {
            ramis.top = 50 + (ramis.height + 2) * i;
            teksts.setText(objekts.struktura[objekts.struktura.length - 1 - i].vertiba.toString());
            teksts.top = ramis.top + (ramis.height / 4);
            attels.add(ramis);
            attels.add(teksts);
            objekts.struktura[i].zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        }
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

export default Strukturas;
<commit_msg>Izveidot un uzzīmēt Rindu<commit_after>
var Strukturas = [
    {
        id: "vienkars_saraksts",
        nosaukums: "Vienkāršsaistīts saraksts",
        izveidot: null
    },
    {
        id: "divkars_saraksts",
        nosaukums: "Divkāršsaistīts saraksts",
        izveidot: null
    },
    {
        id: "steks",
        nosaukums: "Steks",
        izveidot: null
    },
    {
        id: "rinda",
        nosaukums: "Rinda",
        izveidot: null
    },
    {
        id: "kaudze",
        nosaukums: "Kaudze",
        izveidot: null
    },
    {
        id: "binars_koks",
        nosaukums: "Binārs koks",
        izveidot: null
    },
    {
        id: "avl_koks",
        nosaukums: "AVL koks",
        izveidot: null
    },
    {
        id: "meklesanas_koks",
        nosaukums: "Meklēšanas koks",
        izveidot: null
    }
];

var c = 0;

function dabutVertibu() {
    return Math.round(Math.random() * 99);
}

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
        this.nakosais = null;
    };
    this.katramElementam = function(fn) {
        var elem = objekts.struktura;
        fn(elem);
        while (elem.nakosais) {
            elem = elem.nakosais;
            fn(elem);
        }
    };
    this.iegutElementu = function(sakuma) {
        if (sakuma) {
            return objekts.struktura;
        } else {
            var elem = objekts.struktura;
            while (elem.nakosais) {
                elem = elem.nakosais;
            }
            return elem;
        }
    };
    this.pievienot = function(vertiba, sakuma) {
        if (objekts.struktura) {
            var elem = objekts.iegutElementu(sakuma);
            elem.nakosais = new objekts.elements(vertiba);
        } else {
            objekts.struktura = new objekts.elements(vertiba);
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        var i = 0;
        objekts.katramElementam(function(elem) {
            i++;
            ramis.left = 50 + (ramis.width + 20) * i;
            teksts.setText(elem.vertiba.toString());
            teksts.left = ramis.left + (ramis.width / 4);
            attels.add(ramis);
            attels.add(teksts);
            elem.zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        });
        objekts.katramElementam(function(elem) {
            if (elem.nakosais) {
                linija.set({x1: elem.zimejums[0].left + elem.zimejums[0].width / 4 * 3,
                            x2: elem.zimejums[0].left + elem.zimejums[0].width + 40,
                            y1: elem.zimejums[0].top + elem.zimejums[0].height / 5,
                            y2: elem.zimejums[0].top + elem.zimejums[0].height / 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'x1': linija.x2 - 15, 'y1': linija.y1 - 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'y1': linija.y1 + 10});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
            }
        });
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
        this.ieprieksejais = null;
        this.nakosais = null;
    };
    this.katramElementam = function(fn) {
        var elem = objekts.struktura;
        fn(elem);
        while (elem.nakosais) {
            elem = elem.nakosais;
            fn(elem);
        }
    };
    this.iegutElementu = function(sakuma) {
        if (sakuma) {
            return objekts.struktura;
        } else {
            var elem = objekts.struktura;
            while (elem.nakosais) {
                elem = elem.nakosais;
            }
            return elem;
        }
    };
    this.pievienot = function(vertiba, sakuma) {
        if (objekts.struktura) {
            var elem = objekts.iegutElementu(sakuma);
            elem.nakosais = new objekts.elements(vertiba);
            elem.nakosais.ieprieksejais = elem;
        } else {
            objekts.struktura = new objekts.elements(vertiba);
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        var i = 0;
        objekts.katramElementam(function(elem) {
            i++;
            ramis.left = 50 + (ramis.width + 20) * i;
            teksts.setText(elem.vertiba.toString());
            teksts.left = ramis.left + (ramis.width / 4);
            attels.add(ramis);
            attels.add(teksts);
            elem.zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        });
        objekts.katramElementam(function(elem) {
            if (elem.nakosais) {
                linija.set({x1: elem.zimejums[0].left + elem.zimejums[0].width / 4 * 3,
                            x2: elem.zimejums[0].left + elem.zimejums[0].width + 40,
                            y1: elem.zimejums[0].top + elem.zimejums[0].height / 5,
                            y2: elem.zimejums[0].top + elem.zimejums[0].height / 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'x1': linija.x2 - 15, 'y1': linija.y1 - 5});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
                linija.set({'y1': linija.y1 + 10});
                attels.add(linija);
                elem.zimejums.push(linija);
                linija = window.fabric.util.object.clone(linija);
            }
            if (elem.ieprieksejais) {
            linija.set({x1: elem.zimejums[0].left + elem.zimejums[0].width / 4,
                        x2: elem.zimejums[0].left - 20 - elem.zimejums[0].width / 4,
                        y1: elem.zimejums[0].top + elem.zimejums[0].height - elem.zimejums[0].height / 6,
                        y2: elem.zimejums[0].top + elem.zimejums[0].height - elem.zimejums[0].height / 6});
            attels.add(linija);
            elem.zimejums.push(linija);
            linija = window.fabric.util.object.clone(linija);
            linija.set({x1: elem.zimejums[0].left - 20 - elem.zimejums[0].width / 4 + 15,
                        y1: linija.y1 - 5});
            attels.add(linija);
            elem.zimejums.push(linija);
            linija = window.fabric.util.object.clone(linija);
            linija.set({'y1': linija.y1 + 10});
            attels.add(linija);
            elem.zimejums.push(linija);
            linija = window.fabric.util.object.clone(linija);
            }
        });
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = [];
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
    };
    this.pievienot = function(vertiba, sakuma) {
        if (sakuma) {
            objekts.struktura.unshift(new objekts.elements(vertiba));
        } else {
            objekts.struktura.push(new objekts.elements(vertiba));
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        ramis.left = 200;
        teksts.left = 215;
        for (var i = 0; i < objekts.struktura.length; i++) {
            ramis.top = 50 + (ramis.height + 2) * i;
            teksts.setText(objekts.struktura[objekts.struktura.length - 1 - i].vertiba.toString());
            teksts.top = ramis.top + (ramis.height / 4);
            attels.add(ramis);
            attels.add(teksts);
            objekts.struktura[i].zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        }
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = [];
    var objekts = this;
    this.elements = function(vertiba) {
        this.vertiba = vertiba;
        this.zimejums = [];
    };
    this.pievienot = function(vertiba, sakuma) {
        if (sakuma) {
            objekts.struktura.unshift(new objekts.elements(vertiba));
        } else {
            objekts.struktura.push(new objekts.elements(vertiba));
        }
    };
    for (var i = 0; i < elementi; i++) {
        objekts.pievienot(dabutVertibu(), false);
    }
    this.zimet = function(attels, ramis, teksts, linija) {
        for (var i = 0; i < objekts.struktura.length; i++) {
            ramis.left = 50 + (ramis.width + 2) * i;
            teksts.setText(objekts.struktura[i].vertiba.toString());
            teksts.left = ramis.left + (ramis.width / 4);
            attels.add(ramis);
            attels.add(teksts);
            objekts.struktura[i].zimejums = [ramis, teksts];
            ramis = window.fabric.util.object.clone(ramis);
            teksts = window.fabric.util.object.clone(teksts);
        }
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

Strukturas[c++].izveidot = function(elementi) {
    this.struktura = null;
    this.pievienot = function(vertiba, sakuma) {
    };
    this.zimet = function(attels, ramis, teksts, linija) {
    };
    return this;
};

export default Strukturas;
<|endoftext|>


<commit_before>(function($){
  var SELECTED_FILE_ELEM = null;
  var ENABLE_KEY_NAV = true;

  $(document).keydown(function(event) {
    if (!ENABLE_KEY_NAV)
      return true;
    var selection = SELECTED_FILE_ELEM;
    switch (event.keyCode) {
      case 74: // j
        if (selection == null) {
          selection = $('#f0');
        } else {
          do {
            selection = selection.next();
          } while (selection.length > 0 && selection.css('display') == 'none');
        }
        break;
      case 75: // k
        if (selection == null) {
          selection = $('#f0');
        } else {
          do {
            selection = selection.prev();
          } while (selection.length > 0 && selection.css('display') == 'none');
        }
        break;
      case 13: // Enter
      case 79: // o
        if (selection != null) {
          var expander = selection.find('.expander');
          if (expander.length > 0) {
            expander.click();
          } else {
            var href = selection.find('a.file').attr('href');
            if (!href)
              href = selection.find('a.parent').attr('href');
            if (href)
              window.location = href;
          }
        }
        return false;
        break;
      default:
        return true;
    }
    if (selection.length > 0) {
      if (SELECTED_FILE_ELEM != null)
        SELECTED_FILE_ELEM.removeClass('focus');
      selection.addClass('focus');
      SELECTED_FILE_ELEM = selection;
    }
    return false;
  });

  $(function() {
    $('a,input,select,textarea,button')
      .focus(function(event) {
        ENABLE_KEY_NAV = false;
      })
      .blur(function(event) {
        ENABLE_KEY_NAV = true;
      });
  });
})(jQuery);
<commit_msg>TracBrowser: add two more key bindings:  - 'a' for going to the annotate page  - 'l' for going to the (change) log<commit_after>(function($){
  var SELECTED_FILE_ELEM = null;
  var ENABLE_KEY_NAV = true;

  $(document).keydown(function(event) {
    if (!ENABLE_KEY_NAV)
      return true;
    var selection = SELECTED_FILE_ELEM;
    switch (event.keyCode) {
      case 74: // j - next line
        if (selection == null) {
          selection = $('#f0');
          if ( !selection.length )
            selection = $($("#dirlist tr").get(1))
        } else {
          do {
            selection = selection.next();
          } while (selection.length > 0 && selection.css('display') == 'none');
        }
        break;
      case 75: // k - previous line
        if (selection == null) {
          selection = $('#f0');
        } else {
          do {
            selection = selection.prev();
          } while (selection.length > 0 && selection.css('display') == 'none');
        }
        break;
      case 13: // Enter
      case 65: // 'a'nnotate
      case 79: // 'o'pen
        if (selection != null) {
          var expander = selection.find('.expander');
          if (expander.length > 0) {
            expander.click();
          } else {
            var href = selection.find('a.file').attr('href');
            if (!href)
              href = selection.find('a.parent').attr('href');
            if (href) {
              if (event.keyCode == 65)
                href += '?annotate=blame';
              window.location = href;
            }
          }
        }
        return false;
        break;
      case 76: // 'l'og
        if (selection != null) {
          var href = selection.find('td.rev a').attr('href');
          if (href)
            window.location = href;
        }
        break;
      default:
        return true;
    }
    if (selection.length > 0) {
      if (SELECTED_FILE_ELEM != null)
        SELECTED_FILE_ELEM.removeClass('focus');
      selection.addClass('focus');
      SELECTED_FILE_ELEM = selection;
    }
    return false;
  });

  $(function() {
    $('a,input,select,textarea,button')
      .focus(function(event) {
        ENABLE_KEY_NAV = false;
      })
      .blur(function(event) {
        ENABLE_KEY_NAV = true;
      });
  });
})(jQuery);
<|endoftext|>


<commit_before>/**
 * Атлас. Новый
 */
var AT = {};

AT.version = '0.3';
AT.map = null;
AT.filterTags = [];
AT.clusterPoints = null;
AT.regions = [];

AT.init = function(params) {
    console.info('Init Atlas');

    AT.initMap(params);
    AT.initGeocoder();
    AT.initUI();
    AT.initFilters();
    AT.initHacks();

    // Сабмитим форму (показываем Образы России)
    var elems = $('#atlas-filter-form').find('.gray-checked');
    for (var i=0; i<elems.length; i++) {
        var tagId = $(elems[i]).find('span').data('tag');
        if (tagId == 74) {
            $(elems[i]).find('span').click();
            break;
        }
    }
};

AT.initMap = function(params) {
    var map_el = document.getElementById(params.map),
        parameters = {
            roundRobin: {
                tiles: [
                    'http://h01.tiles.tmcrussia.com/map/', 'http://h02.tiles.tmcrussia.com/map/', 'http://h03.tiles.tmcrussia.com/map/','http://h04.tiles.tmcrussia.com/map/',
                    'http://h05.tiles.tmcrussia.com/map/', 'http://h06.tiles.tmcrussia.com/map/', 'http://h07.tiles.tmcrussia.com/map/'
                ]
            },
            coord: new PGmap.Coord(params.center[0], params.center[1], true),
            zoom: params.zoom,
            minZoom: 3
        };

    this.map = new PGmap(map_el, parameters);
    this.map.controls.addControl('slider');

    this.map.balloon.content.parentNode.style.width = '300px';
};

AT.initGeocoder = function() {
    var geocoder = $('.simple-search'),
        resultBox = geocoder.find('.result-box'),
        searchInput = $('#ss_input'),
        searchSubmit = geocoder.find('.submit'),
        searchTerm = searchInput.val();

    searchInput.val('');

    searchInput.autocomplete({
        source: function(request, response) {
            //console.log(request, response);
            //console.log('Try to search:', searchTerm);

            AT.map.search({
                q: request.term,
                type: 'search'
            }, function(r){
                var json = $.parseJSON(r);
                if (json.success) {
                    // console.log(json);
                    var results = [];

                    for (var i in json.res) {

                        var el = json.res[i];

                        // el - найденный элемент (addr|poi)
                        if (el.type == "addr") {
                            for (var j in el.matches) {
                                var match = el.matches[j];

                                var obj = {
                                    label: match.addr,
                                    value: match.addr,
                                    match: match
                                };

                                results.push(obj);
                            }
                        }
                    }

                    response(results);
                }

            });
        },
        select: function (event, ui) {
            //console.log(ui.item.match);
            var lon = ui.item.match.x,
                lat = ui.item.match.y,
                zoom = ui.item.match.zoom;
            AT.map.setCenter(new PGmap.Coord(lon, lat, true), zoom);
        }
    }).data('autocomplete')._renderItem = function(ul, item) {
        return $("

")
            .data("item.autocomplete", item)
            .append('' + item.label + '')
            .appendTo(ul);
    }

};

AT.initUI = function() {
    $('#atlas-filter-form').ajaxForm({
        beforeSubmit: function(){
            //console.log('xxx');
            $('#ajax-loading').show();
        },
        success: function(responseText, statusText, xhr, $form){
            $('#ajax-loading').hide();
            var json = $.parseJSON(responseText);
            if (json.success) {
                var objects = json.result;
            } else {
                console.error(json.message);
            }

            AT.clearMap();

            var elems = $('.atlas-filter-form .tag');
            elems.addClass('disabled');

            if (objects && objects.length) {
                var points = [];
                for (var i in objects) {
                    var point = AT.placePoint(objects[i]);
                    if (point) {
                        points.push(point);
                    }
                }
                //console.log(json.allCategoriesIds);

                for (var i in json.allCategoriesIds) {
                    var tag = json.allCategoriesIds[i];
                    elems.each(function(i, el){
                        var elSpan = $(el).find('span');
                        var tagId = elSpan.data('tag');
                        if (tagId == tag) {
                            $(el).removeClass('disabled');
                        }
                    });
                }

                // clusterize points
                AT.clusterPoints = new PGmap.GeometryLayer({
                    points: points,
                    clusterSize: 100,
                    clusterImage: bundleImagesUri + "/klaster_1.1.png"
                });
                AT.clusterPoints.setClusterImageByCount = function(count) {
                    return "0px 0px";
                };
                AT.clusterPoints.setClusters.callback = function() {
                    for (var n = AT.clusterPoints.clusters.length; n--; ) {
                        (function(cluster){
                            PGmap.Events.addHandlerByName(cluster.element, 'click', function(e){

                                console.log('click on cluster');

                                // Балун для кластера
                                cluster.balloon = AT.map.balloon;

                                var ids = [];
                                for (var i=0; i<cluster.points.length; i++) {
                                    ids.push($(cluster.points[i].container).data('uid'));
                                }
                                // Содержимое балуна
                                //cluster.name = ids.join(',');
                                console.log('cluster points ids:', cluster.name);

                                // Если достигнут последний уровень зума, показываем бабл
                                if ((AT.map.globals.maxZoom() - AT.map.globals.getZoom()) == 1) {
                                    if (! cluster.balloon.element.offsetHeight || cluster.balloon.currEl != cluster ) {

                                        $.ajax({
                                            url: fetchClusterDetailUri,
                                            data: { ids: ids },
                                            success: function(res){
                                                console.log(res);
                                                cluster.name = res;
                                                cluster.balloon.open(cluster);
                                                //cont.style.zIndex = '75';
                                            }
                                        });

                                    } else {
                                        cluster.balloon.close();
                                        //cont.style.zIndex = '73';
                                    }
                                } else {
                                    AT.clusterPoints.globals.mapObject().setCenterByBbox(cluster.bbox);
                                }
                            }, 'click_' + cluster.index);
                            PGmap.Events.addHandlerByName(cluster.element, 'mouseover', function(e){
                                //this.style.backgroundPosition = ( cluster.count <= 10 ) ? "-120px -69px" : ( cluster.count < 100  ) ? "-56px -69px" : "5px -69px";
                            }, 'mouseover_' + cluster.index);
                            PGmap.Events.addHandlerByName(cluster.element, 'mouseout', function(e){
                                //this.style.backgroundPosition = ( cluster.count <= 10 ) ? "-120px 0" : ( cluster.count < 100  ) ? "-56px 0" : "5px 0";
                            }, 'mouseout_' + cluster.index);
                        })(AT.clusterPoints.clusters[n]);
                    }
                };
                AT.clusterPoints.setClusters();
            }
        }
    });

    // Инициализируем список регионов
    var regionsJsonPath = bundleImagesUri + '/../js/regions.json',
        regionsSelector = $('#regions-selector select');
    $.getJSON(regionsJsonPath, function(res){
        AT.regions = res;
        for (var i=0; i<res.length; i++) {
            regionsSelector.append('<option value="'+res[i].name+'">'+res[i].name+'</option>');
        }
        // При выборе региона, зумим карту к нему
        regionsSelector.chosen({ no_results_text:"Не найдено" }).change(function(){
            AT.map.search({
                q: $(this).val(),
                type: 'search'
            }, function(r){
                var json = $.parseJSON(r);
                if (json.success) {
                    var bbox = json.res[0].bbox;
                    var addrBbox = {
                        lon1: PGmap.Utils.mercX(bbox.x1),
                        lon2: PGmap.Utils.mercX(bbox.x2),
                        lat1: PGmap.Utils.mercY(bbox.y1),
                        lat2: PGmap.Utils.mercY(bbox.y2)
                    };
                    AT.map.setCenterByBbox(addrBbox);
                }
            });
        });
    });

};

// Init filters
AT.initFilters = function(){
    $('.atlas-filter-form').find('.simple-filter-options > label > span').click(function(e){
        // перехват обработчика из function.js
        e.preventDefault();
        e.stopPropagation();
        $(this).closest('label').toggleClass('checked');
        // сбор отмеченных тегов
        AT.submitFiltersForm();
    });

    $('.atlas-filter-form').find('.check_all').click(function(e){
        // сбор отмеченных тегов
        AT.submitFiltersForm();
    });
};

AT.clearMap = function() {

    console.info('AT.clearMap');

    var points = AT.map.geometry.get({ type:'points' });

    if (points.length > 0) {
        for (var i=points.length; i--; ) {
            AT.map.geometry.remove(points[i]);
        }

        for (var n = AT.clusterPoints.clusters.length; n--; ) {
            (function(cluster){
                PGmap.Events.removeHandlerByName(cluster.element, 'click',  'click_' + cluster.index);
                PGmap.Events.removeHandlerByName(cluster.element, 'mouseover', 'mouseover_' + cluster.index);
                PGmap.Events.removeHandlerByName(cluster.element, 'mouseout',  'mouseout_' + cluster.index);
            })(AT.clusterPoints.clusters[n]);
        }

        AT.clusterPoints.removeClusters();
    }
};

AT.placePoint = function(object) {

    if (! (object.lon || object.lat)) {
        console.log('Coords is not set properly', object);
        return false;
    }

    if (object.obraz) {

        //console.log( object );

        var point = new PGmap.Point({
                coord: new PGmap.Coord(object.lon, object.lat, true),
                width: 42,
                height: 39,
                backpos: '0 0',
                innerImage: {
                    src: object.imageUrl,
                    width: 50
                }
            });
    } else {
        var point = new PGmap.Point({
                coord: new PGmap.Coord(object.lon, object.lat, true),
                width: 42,
                height: 39,
                backpos: '0 0',
                url: object.icon
            });
    }
    //console.log( $(point.element) );
    $(point.container)
        .data('uid', object.id)
        .css({
            'margin-left': '-12px',
            'margin-top': '-38px'
        });
    AT.map.geometry.add(point);

    // клик по точке
    PGmap.Events.addHandler(point.container, 'click', function(e) {
        var uid = $(point.container).data('uid');
        $.ajax({
            url: fetchMarkerDetailUri,
            data: { id: uid },
            success: function(res) {

                console.log('click on point');

                //point.addContent(res);
                point.name = res;
                point.balloon = AT.map.balloon;
                //PGmap.Events.removeHandler(point.container, 'click', point.toggleBalloon);
                point.toggleBalloon();
            }
        });
    });

    return point;
};

AT.initHacks = function() {
    $('.g-closer').live('click', function(){
        console.log('try to close bubble');
        $(this).closest('.b-balloon').data('point').hideBalloon();
        return false;
    });
};

AT.collectTagsValue = function() {
    var filterTags = [];
    $('.atlas-filter-form').find('.simple-filter-options > label.checked > span').each(function(i,el){
        filterTags.push( $(this).data('tag') );
    });
    $('#category-id').val(filterTags);
    return filterTags;
};

AT.submitFiltersForm = function() {
    console.info('AT.submitFiltersForm');
    // Собираем отмеченные категории
    AT.collectTagsValue();
    // Сабмитим форму
    $('#atlas-filter-form').submit();
};

<commit_msg>Ничего непонятно, но завораживает<commit_after>/**
 * Атлас. Новый
 */
var AT = {};

AT.version = '0.3';
AT.map = null;
AT.filterTags = [];
AT.clusterPoints = null;
AT.regions = [];

AT.init = function(params) {
    console.info('Init Atlas');

    AT.initMap(params);
    AT.initGeocoder();
    AT.initUI();
    AT.initFilters();
    AT.initHacks();

    // Сабмитим форму (показываем Образы России)
    var elems = $('#atlas-filter-form').find('.gray-checked');
    for (var i=0; i<elems.length; i++) {
        var tagId = $(elems[i]).find('span').data('tag');
        if (tagId == 74) {
            $(elems[i]).find('span').click();
            break;
        }
    }
};

AT.initMap = function(params) {
    var map_el = document.getElementById(params.map),
        parameters = {
            roundRobin: {
                tiles: [
                    'http://h01.tiles.tmcrussia.com/map/', 'http://h02.tiles.tmcrussia.com/map/', 'http://h03.tiles.tmcrussia.com/map/','http://h04.tiles.tmcrussia.com/map/',
                    'http://h05.tiles.tmcrussia.com/map/', 'http://h06.tiles.tmcrussia.com/map/', 'http://h07.tiles.tmcrussia.com/map/'
                ]
            },
            coord: new PGmap.Coord(params.center[0], params.center[1], true),
            zoom: params.zoom,
            minZoom: 3
        };

    this.map = new PGmap(map_el, parameters);
    this.map.controls.addControl('slider');

    this.map.balloon.content.parentNode.style.width = '300px';
};

AT.initGeocoder = function() {
    var geocoder = $('.simple-search'),
        resultBox = geocoder.find('.result-box'),
        searchInput = $('#ss_input'),
        searchSubmit = geocoder.find('.submit'),
        searchTerm = searchInput.val();

    searchInput.val('');

    searchInput.autocomplete({
        source: function(request, response) {
            //console.log(request, response);
            //console.log('Try to search:', searchTerm);

            AT.map.search({
                q: request.term,
                type: 'search'
            }, function(r){
                var json = $.parseJSON(r);
                if (json.success) {
                    // console.log(json);
                    var results = [];

                    for (var i in json.res) {

                        var el = json.res[i];

                        // el - найденный элемент (addr|poi)
                        if (el.type == "addr") {
                            for (var j in el.matches) {
                                var match = el.matches[j];

                                var obj = {
                                    label: match.addr,
                                    value: match.addr,
                                    match: match
                                };

                                results.push(obj);
                            }
                        }
                    }

                    response(results);
                }

            });
        },
        select: function (event, ui) {
            //console.log(ui.item.match);
            var lon = ui.item.match.x,
                lat = ui.item.match.y,
                zoom = ui.item.match.zoom;
            AT.map.setCenter(new PGmap.Coord(lon, lat, true), zoom);
        }
    }).data('autocomplete')._renderItem = function(ul, item) {
        return $("

")
            .data("item.autocomplete", item)
            .append('' + item.label + '')
            .appendTo(ul);
    }

};

AT.initUI = function() {
    $('#atlas-filter-form').ajaxForm({
        beforeSubmit: function(){
            //console.log('xxx');
            $('#ajax-loading').show();
        },
        success: function(responseText, statusText, xhr, $form){
            $('#ajax-loading').hide();

            var elems = $('.atlas-filter-form .tag');
            var json = $.parseJSON(responseText);
            if (json.success) {
                var objects = json.result;
                elems.addClass('disabled');
            } else {
                elems.removeClass('disabled');
                console.error(json.message);
            }

            AT.clearMap();

            if (objects && objects.length) {
                var points = [];
                for (var i in objects) {
                    var point = AT.placePoint(objects[i]);
                    if (point) {
                        points.push(point);
                    }
                }
                //console.log(json.allCategoriesIds);

                for (var i in json.allCategoriesIds) {
                    var tag = json.allCategoriesIds[i];
                    elems.each(function(i, el){
                        var elSpan = $(el).find('span');
                        var tagId = elSpan.data('tag');
                        if (tagId == tag) {
                            $(el).removeClass('disabled');
                        }
                    });
                }

                // clusterize points
                AT.clusterPoints = new PGmap.GeometryLayer({
                    points: points,
                    clusterSize: 100,
                    clusterImage: bundleImagesUri + "/klaster_1.1.png"
                });
                AT.clusterPoints.setClusterImageByCount = function(count) {
                    return "0px 0px";
                };
                AT.clusterPoints.setClusters.callback = function() {
                    for (var n = AT.clusterPoints.clusters.length; n--; ) {
                        (function(cluster){
                            PGmap.Events.addHandlerByName(cluster.element, 'click', function(e){

                                console.log('click on cluster');

                                // Балун для кластера
                                cluster.balloon = AT.map.balloon;

                                var ids = [];
                                for (var i=0; i<cluster.points.length; i++) {
                                    ids.push($(cluster.points[i].container).data('uid'));
                                }
                                // Содержимое балуна
                                //cluster.name = ids.join(',');
                                console.log('cluster points ids:', cluster.name);

                                // Если достигнут последний уровень зума, показываем бабл
                                if ((AT.map.globals.maxZoom() - AT.map.globals.getZoom()) == 1) {
                                    if (! cluster.balloon.element.offsetHeight || cluster.balloon.currEl != cluster ) {

                                        $.ajax({
                                            url: fetchClusterDetailUri,
                                            data: { ids: ids },
                                            success: function(res){
                                                console.log(res);
                                                cluster.name = res;
                                                cluster.balloon.open(cluster);
                                                //cont.style.zIndex = '75';
                                            }
                                        });

                                    } else {
                                        cluster.balloon.close();
                                        //cont.style.zIndex = '73';
                                    }
                                } else {
                                    AT.clusterPoints.globals.mapObject().setCenterByBbox(cluster.bbox);
                                }
                            }, 'click_' + cluster.index);
                            PGmap.Events.addHandlerByName(cluster.element, 'mouseover', function(e){
                                //this.style.backgroundPosition = ( cluster.count <= 10 ) ? "-120px -69px" : ( cluster.count < 100  ) ? "-56px -69px" : "5px -69px";
                            }, 'mouseover_' + cluster.index);
                            PGmap.Events.addHandlerByName(cluster.element, 'mouseout', function(e){
                                //this.style.backgroundPosition = ( cluster.count <= 10 ) ? "-120px 0" : ( cluster.count < 100  ) ? "-56px 0" : "5px 0";
                            }, 'mouseout_' + cluster.index);
                        })(AT.clusterPoints.clusters[n]);
                    }
                };
                AT.clusterPoints.setClusters();
            }
        }
    });

    // Инициализируем список регионов
    var regionsJsonPath = bundleImagesUri + '/../js/regions.json',
        regionsSelector = $('#regions-selector select');
    $.getJSON(regionsJsonPath, function(res){
        AT.regions = res;
        for (var i=0; i<res.length; i++) {
            regionsSelector.append('<option value="'+res[i].name+'">'+res[i].name+'</option>');
        }
        // При выборе региона, зумим карту к нему
        regionsSelector.chosen({ no_results_text:"Не найдено" }).change(function(){
            AT.map.search({
                q: $(this).val(),
                type: 'search'
            }, function(r){
                var json = $.parseJSON(r);
                if (json.success) {
                    var bbox = json.res[0].bbox;
                    var addrBbox = {
                        lon1: PGmap.Utils.mercX(bbox.x1),
                        lon2: PGmap.Utils.mercX(bbox.x2),
                        lat1: PGmap.Utils.mercY(bbox.y1),
                        lat2: PGmap.Utils.mercY(bbox.y2)
                    };
                    AT.map.setCenterByBbox(addrBbox);
                }
            });
        });
    });

};

// Init filters
AT.initFilters = function(){
    $('.atlas-filter-form').find('.simple-filter-options > label > span').click(function(e){
        // перехват обработчика из function.js
        e.preventDefault();
        e.stopPropagation();
        $(this).closest('label').toggleClass('checked');
        // сбор отмеченных тегов
        AT.submitFiltersForm();
    });

    $('.atlas-filter-form').find('.check_all').click(function(e){
        // сбор отмеченных тегов
        AT.submitFiltersForm();
    });
};

AT.clearMap = function() {

    console.info('AT.clearMap');

    var points = AT.map.geometry.get({ type:'points' });

    if (points.length > 0) {
        for (var i=points.length; i--; ) {
            AT.map.geometry.remove(points[i]);
        }

        for (var n = AT.clusterPoints.clusters.length; n--; ) {
            (function(cluster){
                PGmap.Events.removeHandlerByName(cluster.element, 'click',  'click_' + cluster.index);
                PGmap.Events.removeHandlerByName(cluster.element, 'mouseover', 'mouseover_' + cluster.index);
                PGmap.Events.removeHandlerByName(cluster.element, 'mouseout',  'mouseout_' + cluster.index);
            })(AT.clusterPoints.clusters[n]);
        }

        AT.clusterPoints.removeClusters();
    }
};

AT.placePoint = function(object) {

    if (! (object.lon || object.lat)) {
        console.log('Coords is not set properly', object);
        return false;
    }

    if (object.obraz) {

        //console.log( object );

        var point = new PGmap.Point({
                coord: new PGmap.Coord(object.lon, object.lat, true),
                width: 42,
                height: 39,
                backpos: '0 0',
                innerImage: {
                    src: object.imageUrl,
                    width: 50
                }
            });
    } else {
        var point = new PGmap.Point({
                coord: new PGmap.Coord(object.lon, object.lat, true),
                width: 42,
                height: 39,
                backpos: '0 0',
                url: 'http://культура.рф/uploads/media/atlas_icon/0001/05/10bbc0516e276f972f46e0586115c1a0af7df695.png' //object.icon
            });
    }
    //console.log( $(point.element) );
    $(point.container)
        .data('uid', object.id)
        .css({
            'margin-left': '-12px',
            'margin-top': '-38px'
        });
    AT.map.geometry.add(point);

    // клик по точке
    PGmap.Events.addHandler(point.container, 'click', function(e) {
        var uid = $(point.container).data('uid');
        $.ajax({
            url: fetchMarkerDetailUri,
            data: { id: uid },
            success: function(res) {

                console.log('click on point');

                //point.addContent(res);
                point.name = res;
                point.balloon = AT.map.balloon;
                //PGmap.Events.removeHandler(point.container, 'click', point.toggleBalloon);
                point.toggleBalloon();
            }
        });
    });

    return point;
};

AT.initHacks = function() {
    $('.g-closer').live('click', function(){
        console.log('try to close bubble');
        $(this).closest('.b-balloon').data('point').hideBalloon();
        return false;
    });
};

AT.collectTagsValue = function() {
    var filterTags = [];
    $('.atlas-filter-form').find('.simple-filter-options > label.checked > span').each(function(i,el){
        filterTags.push( $(this).data('tag') );
    });
    $('#category-id').val(filterTags);
    return filterTags;
};

AT.submitFiltersForm = function() {
    console.info('AT.submitFiltersForm');
    // Собираем отмеченные категории
    AT.collectTagsValue();
    // Сабмитим форму
    $('#atlas-filter-form').submit();
};

<|endoftext|>


<commit_before>var async = require('async');
var moment = require('moment');
var twitter = require('ntwitter');

var models = require('./models');
var settings = require('./settings');

// Rate limit is 180 requests per 15 minutes
// TODO: Use limiter for proper limiting of all Tweeter requests
var LOAD_INTERVAL = 15 * 60 * 1000 / 180;
var MAX_ID_REGEXP = /max_id=(\d+)/;

var twit = new twitter({
    'consumer_key': settings.TWITTER_CONSUMER_KEY,
    'consumer_secret': settings.TWITTER_CONSUMER_SECRET,
    'access_token_key': settings.TWITTER_ACCESS_TOKEN_KEY,
    'access_token_secret': settings.TWITTER_ACCESS_TOKEN_SECRET
});

var max_id = process.argv.length > 2 ? process.argv[2] : null;
var count = 0;
var date = null;
var error_count = 0;

function next() {
    if (!date) {
        date = moment();
    }
    date.subtract('days', 1);
    max_id = null;
    if (moment() - date > 14 * 24 * 60 * 60 * 1000) { // 14 days
        process.exit(0);
    }
    else {
        setTimeout(loadtweets, LOAD_INTERVAL);
    }
}

function loadtweets() {
    var params = {'include_entities': true, 'count': 100, 'max_id': max_id, 'q': settings.TWITTER_QUERY.join(' OR ') + (date ? ' until:' + date.format('YYYY-MM-DD') : '')};
    console.log("Making request, max_id = %s, date = %s", max_id, date);
    twit.get('/search/tweets.json', params, function(err, data) {
        if (err) {
            if (err.statusCode === 500 && error_count < 3) {
                console.error("Twitter fetch error, retrying", err);
                error_count++;
                setTimeout(loadtweets, LOAD_INTERVAL);
            }
            else {
                console.error("Twitter fetch error", err);
                process.exit(1);
            }
            return;
        }

        error_count = 0;

        if (data.statuses.length === 0) {
            console.log("%s new tweets fetched overall", count);
            next();
            return;
        }

        async.forEach(data.statuses, function (tweet, cb) {
            models.Post.storeTweet(tweet, 'search', function (err, tweet) {
                if (err) {
                    console.error(err);
                    return;
                }

                if (tweet) {
                    count++;
                }
            });

            // We handle error independently
            cb(null);
        }, function (err) {
            console.log("%s new tweets fetched overall", count);

            var max_id_match = MAX_ID_REGEXP.exec(data.search_metadata.next_results);
            if (!max_id_match) {
                next();
                return;
            }

            max_id = max_id_match[1];

            setTimeout(loadtweets, LOAD_INTERVAL);
        });
    });
}

loadtweets();
<commit_msg>Code style.<commit_after>var async = require('async');
var moment = require('moment');
var twitter = require('ntwitter');

var models = require('./models');
var settings = require('./settings');

// Rate limit is 180 requests per 15 minutes
// TODO: Use limiter for proper limiting of all Tweeter requests
var LOAD_INTERVAL = 15 * 60 * 1000 / 180;
var MAX_ID_REGEXP = /max_id=(\d+)/;

var twit = new twitter({
    'consumer_key': settings.TWITTER_CONSUMER_KEY,
    'consumer_secret': settings.TWITTER_CONSUMER_SECRET,
    'access_token_key': settings.TWITTER_ACCESS_TOKEN_KEY,
    'access_token_secret': settings.TWITTER_ACCESS_TOKEN_SECRET
});

var maxId = process.argv.length > 2 ? process.argv[2] : null;
var count = 0;
var date = null;
var errorCount = 0;

function next() {
    if (!date) {
        date = moment();
    }
    date.subtract('days', 1);
    maxId = null;
    if (moment() - date > 14 * 24 * 60 * 60 * 1000) { // 14 days
        process.exit(0);
    }
    else {
        setTimeout(loadtweets, LOAD_INTERVAL);
    }
}

function loadtweets() {
    var params = {'include_entities': true, 'count': 100, 'max_id': maxId, 'q': settings.TWITTER_QUERY.join(' OR ') + (date ? ' until:' + date.format('YYYY-MM-DD') : '')};
    console.log("Making request, max_id = %s, date = %s", maxId, date);
    twit.get('/search/tweets.json', params, function(err, data) {
        if (err) {
            if (err.statusCode === 500 && errorCount < 3) {
                console.error("Twitter fetch error, retrying", err);
                errorCount++;
                setTimeout(loadtweets, LOAD_INTERVAL);
            }
            else {
                console.error("Twitter fetch error", err);
                process.exit(1);
            }
            return;
        }

        errorCount = 0;

        if (data.statuses.length === 0) {
            console.log("%s new tweets fetched overall", count);
            next();
            return;
        }

        async.forEach(data.statuses, function (tweet, cb) {
            models.Post.storeTweet(tweet, 'search', function (err, tweet) {
                if (err) {
                    console.error(err);
                    return;
                }

                if (tweet) {
                    count++;
                }
            });

            // We handle error independently
            cb(null);
        }, function (err) {
            console.log("%s new tweets fetched overall", count);

            var max_id_match = MAX_ID_REGEXP.exec(data.search_metadata.next_results);
            if (!max_id_match) {
                next();
                return;
            }

            maxId = max_id_match[1];

            setTimeout(loadtweets, LOAD_INTERVAL);
        });
    });
}

loadtweets();
<|endoftext|>