<commit_before>module.exports = {
  extends: [
    'eslint-config-airbnb',
  ],
  env: {
    browser: true,
    node: true,
    mocha: true,
    jest: true,
    es6: true,
  },
  parser: 'babel-eslint',
  parserOptions: {
    ecmaVersion: 6,
    ecmaFeatures: {
      jsx: true,
      experimentalObjectRestSpread: true,
    },
  },
  plugins: [
    'react',
    'babel',
  ],
  rules: {
    curly: [
      2,
      'all',
    ],
    'react/no-did-mount-set-state': 0,
    'react/forbid-prop-types': 0,
    'jsx-a11y/no-static-element-interactions': 0,
    'jsx-a11y/click-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-element-to-interactive-role': 0,
    'jsx-a11y/no-noninteractive-element-interactions': 0,
    'jsx-a11y/mouse-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-tabindex': 0,
    'array-callback-return': 0,
    'comma-dangle': ['error', {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      imports: 'always-multiline',
      exports: 'always-multiline',
      functions: 'never',
    }],
    'func-names': 0,
    'arrow-body-style': 0,
    'react/prop-types': 0,
    'react/jsx-filename-extension': 0,
    'import/no-unresolved': 0,
    'no-param-reassign': 0,
    'no-return-assign': 0,
    'max-len': [
      2,
      {
        code: 120,
      },
    ],
    'consistent-return': 0,
    'class-methods-use-this': 0,
    'no-plusplus': 0,
    'no-underscore-dangle': 0,
    'no-empty': ['error', {
      allowEmptyCatch: true,
    }],
    'import/no-extraneous-dependencies': [
      0,
      {
        devDependencies: [
          '/src',
          '/test',
        ],
        peerDependencies: 0,
      },
    ],
    'prefer-const': ['error', {
      destructuring: 'all',
    }],
    'prefer-destructuring': ['error', {
      VariableDeclarator: {
        array: false,
        object: true,
      },
      AssignmentExpression: {
        array: false,
        object: false,
      },
    }, {
      enforceForRenamedProperties: false,
    }],
  },
};
<commit_msg>refactor: no-sync: 1<commit_after>module.exports = {
  extends: [
    'eslint-config-airbnb',
  ],
  env: {
    browser: true,
    node: true,
    mocha: true,
    jest: true,
    es6: true,
  },
  parser: 'babel-eslint',
  parserOptions: {
    ecmaVersion: 6,
    ecmaFeatures: {
      jsx: true,
      experimentalObjectRestSpread: true,
    },
  },
  plugins: [
    'react',
    'babel',
  ],
  rules: {
    curly: [
      2,
      'all',
    ],
    'no-sync': 1,
    'react/no-did-mount-set-state': 0,
    'react/forbid-prop-types': 0,
    'jsx-a11y/no-static-element-interactions': 0,
    'jsx-a11y/click-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-element-to-interactive-role': 0,
    'jsx-a11y/no-noninteractive-element-interactions': 0,
    'jsx-a11y/mouse-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-tabindex': 0,
    'array-callback-return': 0,
    'comma-dangle': ['error', {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      imports: 'always-multiline',
      exports: 'always-multiline',
      functions: 'never',
    }],
    'func-names': 0,
    'arrow-body-style': 0,
    'react/prop-types': 0,
    'react/jsx-filename-extension': 0,
    'import/no-unresolved': 0,
    'no-param-reassign': 0,
    'no-return-assign': 0,
    'max-len': [
      2,
      {
        code: 120,
      },
    ],
    'consistent-return': 0,
    'class-methods-use-this': 0,
    'no-plusplus': 0,
    'no-underscore-dangle': 0,
    'no-empty': ['error', {
      allowEmptyCatch: true,
    }],
    'import/no-extraneous-dependencies': [
      0,
      {
        devDependencies: [
          '/src',
          '/test',
        ],
        peerDependencies: 0,
      },
    ],
    'prefer-const': ['error', {
      destructuring: 'all',
    }],
    'prefer-destructuring': ['error', {
      VariableDeclarator: {
        array: false,
        object: true,
      },
      AssignmentExpression: {
        array: false,
        object: false,
      },
    }, {
      enforceForRenamedProperties: false,
    }],
  },
};
<|endoftext|>


<commit_before>/**
 * Microlib for translations with support for placeholders and multiple plural forms.
 *
 * v0.0.2
 *
 * Usage:
 * var messages = {
 *  translationKey: 'translationValue',
 *  moduleA: {
 *    translationKey: 'value123'
 *  }
 * }
 *
 * var options = {
 *   // These are the defaults:
 *   debug: false, //[Boolean]: Logs missing translations to console and add "@@" around output if `true`.
 *   namespaceSplitter: '::', //[String|RegExp]: Customizes the translationKey namespace splitter.
 *   pluralize: function(n,translKey){ return Math.abs(n); } //[Function(count,translationKey)]: Provides a custom pluralization mapping function.
 * }
 *
 * var t = libTranslate.getTranslationFunction(messages, [options])
 *
 * t('translationKey')
 * t('translationKey', count)
 * t('translationKey', {replaceKey: 'replacevalue'})
 * t('translationKey', count, {replaceKey: 'replacevalue'})
 * t('translationKey', {replaceKey: 'replacevalue'}, count)
 * t('moduleA::translationKey')
 *
 *
 * @author Jonas Girnatis <dermusterknabe@gmail.com>
 * @licence May be freely distributed under the MIT license.
 */

/* global console, module */

'use strict';

var isObject = function(obj) {
  return obj  &&  typeof obj === 'object';
};

module.exports = function(messageObject, options) {
  var debug = options && options.debug;

  function getTranslationValue(translationKey) {
    var transValue = tFunc.keys[translationKey];
    if( transValue == null ) {
      var path = translationKey.split( (tFunc.opts && tFunc.opts.namespaceSplitter) || '::' );
      var i = 0;
      var len = path.length;
      if ( len > 1 )
      {
        // Start walking
        transValue = tFunc.keys;
        while ( len > i ) {
          transValue = transValue[ path[i] || '' ];
          if ( transValue == null ) {
            break;
          }
          i++;
        }
      }
    }
    return transValue;
  }

  function getPluralValue(translation, count) {
    // Opinionated assumption: Pluralization rules are the same for negative and positive values.
    // By normalizing all values to positive, pluralization functions become simpler, and less error-prone by accident.
    var mappedCount = Math.abs(count);

    if(translation[mappedCount] != null){
      translation = translation[mappedCount];
    } else {
      var plFunc = (tFunc.opts||{}).pluralize;
      mappedCount = plFunc ? plFunc( mappedCount, translation ) : mappedCount;
      if(translation[mappedCount] != null){
        translation = translation[mappedCount];
      } else if(translation.n != null) {
        translation = translation.n;
      } else {
        debug && console.warn('No plural forms found for "' + count + '" in', translation);
      }
    }
    return translation;
  }

  function replacePlaceholders(translation, replacements, count) {
    return translation.replace(/\{(\w*)\}/g, function (match, key) {
      var val = replacements[key];
      if (!replacements.hasOwnProperty(key)) {
        if ( key === 'n' || count != null) {
          val = count;
        } else {
          debug && console.warn('No "' + key + '" in placeholder object:', replacements);
          val = match;
        }
      }
      return val;
    });
  }

  var tFunc = function (translationKey, count, replacements) {
    var translation = getTranslationValue(translationKey);
    var complex = arguments.length > 1;

    if ( complex )
    {
      if ( isObject(count) ) {
        var tmp = replacements;
        replacements = count;
        count = tmp;
      }
      replacements = replacements || {};
      count = typeof count === 'number' ? count : null;

      if ( count != null && isObject(translation) ) {
        //get appropriate plural translation string
        translation = getPluralValue(translation, count);
      }
    }

    if ( typeof translation !== 'string' ) {
      translation = translationKey;
      if (debug) {
          translation = '@@' + translation + '@@';
          console.warn('Translation for "' + translationKey + '" not found.');
      }
    } else if ( complex || debug ) {
      translation = replacePlaceholders(translation, replacements, count);
    }

    return translation;
  };

  tFunc.keys = messageObject || {};
  tFunc.opts = options || {};

  return tFunc;
};
<commit_msg>Expose as `window.translatejs` in browsers<commit_after>/**
 * Microlib for translations with support for placeholders and multiple plural forms.
 *
 * v0.0.2
 *
 * Usage:
 * var messages = {
 *  translationKey: 'translationValue',
 *  moduleA: {
 *    translationKey: 'value123'
 *  }
 * }
 *
 * var options = {
 *   // These are the defaults:
 *   debug: false, //[Boolean]: Logs missing translations to console and add "@@" around output if `true`.
 *   namespaceSplitter: '::', //[String|RegExp]: Customizes the translationKey namespace splitter.
 *   pluralize: function(n,translKey){ return Math.abs(n); } //[Function(count,translationKey)]: Provides a custom pluralization mapping function.
 * }
 *
 * var t = libTranslate.getTranslationFunction(messages, [options])
 *
 * t('translationKey')
 * t('translationKey', count)
 * t('translationKey', {replaceKey: 'replacevalue'})
 * t('translationKey', count, {replaceKey: 'replacevalue'})
 * t('translationKey', {replaceKey: 'replacevalue'}, count)
 * t('moduleA::translationKey')
 *
 *
 * @author Jonas Girnatis <dermusterknabe@gmail.com>
 * @licence May be freely distributed under the MIT license.
 */

/* global console, module */
(function(){
  'use strict';

  var isObject = function(obj) {
    return obj  &&  typeof obj === 'object';
  };

  var translatejs = function(messageObject, options) {

    var debug = options && options.debug;

    function getTranslationValue(translationKey) {
      var transValue = tFunc.keys[translationKey];
      if( transValue == null ) {
        var path = translationKey.split( (tFunc.opts && tFunc.opts.namespaceSplitter) || '::' );
        var i = 0;
        var len = path.length;
        if ( len > 1 )
        {
          // Start walking
          transValue = tFunc.keys;
          while ( len > i ) {
            transValue = transValue[ path[i] || '' ];
            if ( transValue == null ) {
              break;
            }
            i++;
          }
        }
      }
      return transValue;
    }

    function getPluralValue(translation, count) {
      // Opinionated assumption: Pluralization rules are the same for negative and positive values.
      // By normalizing all values to positive, pluralization functions become simpler, and less error-prone by accident.
      var mappedCount = Math.abs(count);

      if(translation[mappedCount] != null){
        translation = translation[mappedCount];
      } else {
        var plFunc = (tFunc.opts||{}).pluralize;
        mappedCount = plFunc ? plFunc( mappedCount, translation ) : mappedCount;
        if(translation[mappedCount] != null){
          translation = translation[mappedCount];
        } else if(translation.n != null) {
          translation = translation.n;
        } else {
          debug && console.warn('No plural forms found for "' + count + '" in', translation);
        }
      }
      return translation;
    }

    function replacePlaceholders(translation, replacements, count) {
      return translation.replace(/\{(\w*)\}/g, function (match, key) {
        var val = replacements[key];
        if (!replacements.hasOwnProperty(key)) {
          if ( key === 'n' || count != null) {
            val = count;
          } else {
            debug && console.warn('No "' + key + '" in placeholder object:', replacements);
            val = match;
          }
        }
        return val;
      });
    }

    var tFunc = function (translationKey, count, replacements) {
      var translation = getTranslationValue(translationKey);
      var complex = arguments.length > 1;

      if ( complex )
      {
        if ( isObject(count) ) {
          var tmp = replacements;
          replacements = count;
          count = tmp;
        }
        replacements = replacements || {};
        count = typeof count === 'number' ? count : null;

        if ( count != null && isObject(translation) ) {
          //get appropriate plural translation string
          translation = getPluralValue(translation, count);
        }
      }

      if ( typeof translation !== 'string' ) {
        translation = translationKey;
        if (debug) {
            translation = '@@' + translation + '@@';
            console.warn('Translation for "' + translationKey + '" not found.');
        }
      } else if ( complex || debug ) {
        translation = replacePlaceholders(translation, replacements, count);
      }

      return translation;
    };

    tFunc.keys = messageObject || {};
    tFunc.opts = options || {};

    return tFunc;
  };

  if ( typeof module !== 'undefined' && module.exports ) {
    module.exports = translatejs;
  } else {
    window.translatejs = translatejs;
  }

})();
<|endoftext|>


<commit_before>var cancelEvents = [
  'touchstart',
  'touchmove',
  'touchcancel',
  'touchenter',
  'touchleave',
]

var endEvents = [
  'touchend',
]

module.exports = Tap

function Tap(callback) {
  // to keep track of the original listener
  listener.handler = callback

  return listener

  // el.addEventListener('touchstart', listener)
  function listener(e1) {
    // tap should only happen with a single finger
    if (e1.touches.length > 1 || e1.defaultPrevented)
      return

    var el = this

    cancelEvents.forEach(function (event) {
      el.addEventListener(event, cleanup)
    })

    endEvents.forEach(function (event) {
      el.addEventListener(event, done)
    })

    function done(e2) {
      cleanup()

      // if handled by some other handler
      if (e1.defaultPrevented || e2.defaultPrevented)
        return
      // make sure a touchstart event didn't occur outside of the element
      if (e2.touches.length > 1)
        return

      var preventDefault = e1.preventDefault
      var stopPropagation = e1.stopPropagation

      e2.stopPropagation = function () {
        stopPropagation.call(e1)
        stopPropagation.call(e2)
      }

      e2.preventDefault = function () {
        preventDefault.call(e1)
        preventDefault.call(e2)
      }

      // calls the handler with the `end` event,
      // but i don't think it matters.
      callback.call(el, e2)
    }

    function cleanup() {
      cancelEvents.forEach(function (event) {
        el.removeEventListener(event, cleanup)
      })

      endEvents.forEach(function (event) {
        el.removeEventListener(event, done)
      })
    }
  }
}<commit_msg>omg propagation actually works now<commit_after>var cancelEvents = [
  'touchmove',
  'touchcancel',
  'touchstart',
]

var endEvents = [
  'touchend',
]

module.exports = Tap

function Tap(callback) {
  // to keep track of the original listener
  listener.handler = callback

  return listener

  // el.addEventListener('touchstart', listener)
  function listener(e1) {
    // tap should only happen with a single finger
    if (e1.touches.length > 1)
      return

    var el = this

    cancelEvents.forEach(function (event) {
      document.addEventListener(event, cleanup)
    })

    endEvents.forEach(function (event) {
      document.addEventListener(event, done)
    })

    function done(e2) {
      // since touchstart is added on the same tick
      // and because of bubbling,
      // it'll execute this on the same touchstart.
      // this filters out the same touchstart event.
      if (e1 === e2)
        return

      cleanup()

      // already handled
      if (e2.defaultPrevented)
        return

      var preventDefault = e1.preventDefault
      var stopPropagation = e1.stopPropagation

      e2.stopPropagation = function () {
        stopPropagation.call(e1)
        stopPropagation.call(e2)
      }

      e2.preventDefault = function () {
        preventDefault.call(e1)
        preventDefault.call(e2)
      }

      // calls the handler with the `end` event,
      // but i don't think it matters.
      callback.call(el, e2)
    }

    function cleanup(e2) {
      if (e1 === e2)
        return

      cancelEvents.forEach(function (event) {
        document.removeEventListener(event, cleanup)
      })

      endEvents.forEach(function (event) {
        document.removeEventListener(event, done)
      })
    }
  }
}<|endoftext|>


<commit_before>module.exports = {
  extends: [
    'eslint-config-airbnb',
  ],
  env: {
    browser: true,
    node: true,
    mocha: true,
    jest: true,
    es6: true,
  },
  parser: 'babel-eslint',
  parserOptions: {
    ecmaVersion: 6,
    ecmaFeatures: {
      jsx: true,
      experimentalObjectRestSpread: true,
    },
  },
  plugins: [
    'react',
    'babel',
  ],
  rules: {
    curly: [
      2,
      'all',
    ],
    'no-sync': 1,
    'react/no-did-mount-set-state': 0,
    'react/forbid-prop-types': 0,
    'jsx-a11y/no-static-element-interactions': 0,
    'jsx-a11y/click-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-element-to-interactive-role': 0,
    'jsx-a11y/no-noninteractive-element-interactions': 0,
    'jsx-a11y/mouse-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-tabindex': 0,
    'jsx-a11y/anchor-is-valid': 0,
    'array-callback-return': 0,
    'comma-dangle': ['error', {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      imports: 'always-multiline',
      exports: 'always-multiline',
      functions: 'never',
    }],
    'func-names': 0,
    'arrow-body-style': 0,
    'react/prop-types': 0,
    'react/jsx-filename-extension': 0,
    'import/no-unresolved': 0,
    'no-param-reassign': 0,
    'no-return-assign': 0,
    'no-mixed-operators': [
      'error', {
        groups: [['&', '|', '^', '~', '<<', '>>', '>>>'], ['&&', '||']],
        allowSamePrecedence: true,
      },
    ],
    'max-len': [
      2,
      {
        code: 120,
      },
    ],
    'consistent-return': 0,
    'class-methods-use-this': 0,
    'no-plusplus': 0,
    'no-underscore-dangle': 0,
    'no-empty': ['error', {
      allowEmptyCatch: true,
    }],
    'import/no-extraneous-dependencies': [
      0,
      {
        devDependencies: [
          '/src',
          '/test',
        ],
        peerDependencies: 0,
      },
    ],
    'prefer-const': ['error', {
      destructuring: 'all',
    }],
    'prefer-destructuring': ['error', {
      VariableDeclarator: {
        array: false,
        object: true,
      },
      AssignmentExpression: {
        array: false,
        object: false,
      },
    }, {
      enforceForRenamedProperties: false,
    }],
  },
};
<commit_msg>feat: support prettier<commit_after>module.exports = {
  extends: [
    'eslint-config-airbnb',
  ],
  env: {
    browser: true,
    node: true,
    mocha: true,
    jest: true,
    es6: true,
  },
  parser: 'babel-eslint',
  parserOptions: {
    ecmaVersion: 6,
    ecmaFeatures: {
      jsx: true,
      experimentalObjectRestSpread: true,
    },
  },
  plugins: [
    'react',
    'babel',
  ],
  rules: {
    'arrow-parens': 0,
    'function-paren-newline': 0,
    'object-curly-newline': 0,
    'space-before-function-paren': 0,

    curly: [
      2,
      'all',
    ],
    'no-sync': 1,
    'react/no-did-mount-set-state': 0,
    'react/forbid-prop-types': 0,
    'jsx-a11y/no-static-element-interactions': 0,
    'jsx-a11y/click-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-element-to-interactive-role': 0,
    'jsx-a11y/no-noninteractive-element-interactions': 0,
    'jsx-a11y/mouse-events-have-key-events': 0,
    'jsx-a11y/no-noninteractive-tabindex': 0,
    'jsx-a11y/anchor-is-valid': 0,
    'array-callback-return': 0,
    'comma-dangle': ['error', {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      imports: 'always-multiline',
      exports: 'always-multiline',
      functions: 'never',
    }],
    'func-names': 0,
    'arrow-body-style': 0,
    'react/prop-types': 0,
    'react/jsx-filename-extension': 0,
    'import/no-unresolved': 0,
    'no-param-reassign': 0,
    'no-return-assign': 0,
    'no-mixed-operators': [
      'error', {
        groups: [['&', '|', '^', '~', '<<', '>>', '>>>'], ['&&', '||']],
        allowSamePrecedence: true,
      },
    ],
    'max-len': [
      2,
      {
        code: 120,
      },
    ],
    'consistent-return': 0,
    'class-methods-use-this': 0,
    'no-plusplus': 0,
    'no-underscore-dangle': 0,
    'no-empty': ['error', {
      allowEmptyCatch: true,
    }],
    'import/no-extraneous-dependencies': [
      0,
      {
        devDependencies: [
          '/src',
          '/test',
        ],
        peerDependencies: 0,
      },
    ],
    'prefer-const': ['error', {
      destructuring: 'all',
    }],
    'prefer-destructuring': ['error', {
      VariableDeclarator: {
        array: false,
        object: true,
      },
      AssignmentExpression: {
        array: false,
        object: false,
      },
    }, {
      enforceForRenamedProperties: false,
    }],
  },
};
<|endoftext|>


<commit_before>var query = require( './src/query' );

module.exports = ( txt_query ) => {

    return (new query( txt_query ) );

};
<commit_msg>Export each module individually<commit_after>var query =

module.exports = {

    charmap : require( './src/charmap' ),
    error   : require( './src/error' ),
    expr    : require( './src/expr' ),
    lex     : require( './src/lex' ),
    parse   : require( './src/parse' ),
    query   : require( './src/query' ),
    site    : require( './src/site' ),
    token   : require( './src/token' )

};
<|endoftext|>


<commit_before>// var allowCrossDomain = function(req, res, next) {
//     res.header('Access-Control-Allow-Origin', '*');
//     res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
//     res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

//     // intercept OPTIONS method
//     if ('OPTIONS' == req.method) {
//       res.send(200);
//     }
//     else {
//       next();
//     }
// };

var app = require('express')();
var http = require('http').Server(app);
// var cors = require('cors');
var io = require('socket.io')(http);

io.set('transports', [
        	'websocket',
        	'flashsocket',
        	'htmlfile',
        	'xhr-polling',
        	'jsonp-polling'
		    ]);

io.configure( function(){
    io.set('origin', '*');
    // io.set('origins', "http://yaps.herokuapp.com" );
});
// io.set("origins", "https://yaps.herokuapp.com");
// io.set("origins","*:*");

// Enables CORS
// var enableCORS = function(req, res, next) {
//     res.header('Access-Control-Allow-Origin', '*');
//     res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
//     res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

//     // intercept OPTIONS method
//     if ('OPTIONS' == req.method) {
//       res.send(200);
//     }
//     else {
//       next();
//     }
// };

// // enable CORS!
// app.use(enableCORS);
// app.use(cors({credentials: true}));

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*:*');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    // debugger;
    // intercept OPTIONS method
    if ('OPTIONS' == req.method) {
      res.send(200);
    }
    else {
      next();
    }
};

// app.use(allowCrossDomain);

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(allowCrossDomain);
  app.use(app.router);
  app.use(express.static(path.join(application_root, "public")));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// io.configure(function () {
//   io.set("transports", ["xhr-polling"]);
//   io.set("polling duration", 10);
// });

// var cors = require('cors'); app.use(cors());

// io.set('transports', [            // all transports (optional if you want flashsocket)
//         'websocket'
//         , 'flashsocket'
//         , 'htmlfile'
//         , 'xhr-polling'
//         , 'jsonp-polling'
//     ]);
// io.set('origins', '*:*');

// app.configure(function () {
//   app.use(allowCrossDomain);
//   app.use(express.bodyParser());
//   app.use(express.methodOverride());
//   app.use(app.router);
//   app.use(express.static(path.join(application_root, "public")));
//   app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
// });

// var username = confirm("Username?");
var url = "http://yaps.herokuapp.com/"

// app.use(allowCrossDomain);

app.get(url, function(req, res){
  res.sendfile('index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');
  socket.on('chat message', function(msg){
  	console.log('message: ' + msg);
  });
});

// // broadcast to all
// io.emit('some event', { for: 'everyone' });

// // broadcast to everyone except for certain socket
// io.on('connection', function(socket){
// 	socket.broadcast.emit('hi');
// });

io.on('connection', function(socket){
	socket.on('chat message', function(msg){
		io.emit('chat message', msg);
	});
});

// http.listen(3001, function(){
//   console.log('listening on *:3001');
// });

http.listen(url, function(){
  console.log('listening to' + url);
});<commit_msg>alknslksn<commit_after>// var allowCrossDomain = function(req, res, next) {
//     res.header('Access-Control-Allow-Origin', '*');
//     res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
//     res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

//     // intercept OPTIONS method
//     if ('OPTIONS' == req.method) {
//       res.send(200);
//     }
//     else {
//       next();
//     }
// };

var app = require('express')();
var http = require('http').Server(app);
// var cors = require('cors');
var io = require('socket.io')(http);

io.set('transports', [
        	'websocket',
        	'flashsocket',
        	'htmlfile',
        	'xhr-polling',
        	'jsonp-polling'
		    ]);

io.configure( function(){
    io.set('origin', '*');
    // io.set('origins', "http://yaps.herokuapp.com" );
});
// io.set("origins", "https://yaps.herokuapp.com");
// io.set("origins","*:*");

// Enables CORS
// var enableCORS = function(req, res, next) {
//     res.header('Access-Control-Allow-Origin', '*');
//     res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
//     res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

//     // intercept OPTIONS method
//     if ('OPTIONS' == req.method) {
//       res.send(200);
//     }
//     else {
//       next();
//     }
// };

// // enable CORS!
// app.use(enableCORS);
// app.use(cors({credentials: true}));

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*:*');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    // debugger;
    // intercept OPTIONS method
    if ('OPTIONS' == req.method) {
      res.send(200);
    }
    else {
      next();
    }
};

// app.use(allowCrossDomain);

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(allowCrossDomain);
  app.use(app.router);
  app.use(express.static(path.join(application_root, "public")));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// io.configure(function () {
//   io.set("transports", ["xhr-polling"]);
//   io.set("polling duration", 10);
// });

// var cors = require('cors'); app.use(cors());

// io.set('transports', [            // all transports (optional if you want flashsocket)
//         'websocket'
//         , 'flashsocket'
//         , 'htmlfile'
//         , 'xhr-polling'
//         , 'jsonp-polling'
//     ]);
// io.set('origins', '*:*');

// app.configure(function () {
//   app.use(allowCrossDomain);
//   app.use(express.bodyParser());
//   app.use(express.methodOverride());
//   app.use(app.router);
//   app.use(express.static(path.join(application_root, "public")));
//   app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
// });

// var username = confirm("Username?");
var url = "http://yaps.herokuapp.com/"

// app.use(allowCrossDomain);

app.get(url, function(req, res){
  res.sendfile('index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');
  socket.on('chat message', function(msg){
  	console.log('message: ' + msg);
  });
});

// // broadcast to all
// io.emit('some event', { for: 'everyone' });

// // broadcast to everyone except for certain socket
// io.on('connection', function(socket){
// 	socket.broadcast.emit('hi');
// });

io.on('connection', function(socket){
	socket.on('chat message', function(msg){
		io.emit('chat message', msg);
	});
});

// http.listen(3001, function(){
//   console.log('listening on *:3001');
// });

http.listen(url, function(){
  console.log('listening to' + url);
});

io.connect('http://yaps.herokuapp.com');<|endoftext|>


<commit_before>import {
  timer,
  timerReplace,
  timerFlush
} from "./src/timer";

export {
  timer,
  timerReplace,
  timerFlush
};
<commit_msg>Concise exports.<commit_after>export {
  timer,
  timerReplace,
  timerFlush
} from "./src/timer";
<|endoftext|>


<commit_before>

describe('makeBasicScript', function() {

  Yo.init({});
  Yo.add('hello', function() {
    return "Hello!";
  });

  it('Should return "Hello!"', function() {
    expect(Yo.modules.hello).toBe('Hello!');
  });
});<commit_msg>Created failed test to test<commit_after>

describe('makeBasicScript', function() {

  Yo.init({});
  Yo.add('hello', function() {
    return "Hello!";
  });

  it('Should return "Hello!"', function() {
    expect(Yo.modules.hello).toBe('eggsa!');
  });
});<|endoftext|>


<commit_before>var configTool = require('./lib/config');

module.exports = function(userConfig){
	'use strict';

	var _self = this || {};

	_self.config = new configTool.setup(userConfig);

	_self.config.gracefulExit = _self.config.gracefulExit || new require('./lib/gracefulexit')(_self.config);
	_self.config.sendMessage = _self.config.sendMessage || new require('./lib/sendmessage')(_self.config);
	_self.config.startup = _self.config.startup || new require('./lib/startup')(_self.config);
	_self.config.shutdown = _self.config.shutdown || new require('./lib/shutdown')(_self.config);

	if(userConfig && userConfig.extendFirestarter) userConfig.extendFirestarter(_self.config);

	process.on('uncaughtException', function(err) {
	    _self.config.logger.info('Uncaught Exception: '+err);
	    _self.config.logger.info(err.stack);
	    _self.config.sendMessage('offline');
		_self.config.shutdown(null, true);
	});

	process.on('message', function(message) {
		if (message === 'ping') {
			_self.config.sendMessage('pong');
		} else if (message === 'shutdown') {
			_self.config.logger.info('Received shutdown message from process instanciator');
			_self.config.sendMessage('offline');
			_self.config.shutdown(null, true);
		}
	});

	process.on('SIGINT', function() {
		_self.config.logger.info('');
		_self.config.logger.info('Received shutdown message from SIGINT (ctrl+c)');
		_self.config.sendMessage('offline');
		_self.config.shutdown(null, true);
	});

	if(!_self.config.serverDomain) _self.config.serverDomain = _self.config.domain.create();

	_self.config.serverDomain.on('error', function(err){
		_self.config.sendMessage('offline');
		_self.config.logger.info('Domain Error: '+err);
	    _self.config.logger.info(err.stack);
	    _self.config.shutdown(null, true);
	});

	return {

		config : _self.config

	  , shutdown : _self.config.shutdown

	  , startup : _self.config.startup

	  , getApp : function(){

			return _self.config.app;
		}

	  , getServer : function(){

			return _self.config.server;
		}

	  , getHttp : function(){

			return _self.config.http;
		}

	  , getServerDomain : function(){

			return _self.config.serverDomain;
		}
	};
};
<commit_msg>Updates<commit_after>var configTool = require('./lib/config');

module.exports = function(userConfig){
	'use strict';

	var _self = this || {};

	_self.config = new configTool.setup(userConfig);

	_self.config.gracefulExit = _self.config.gracefulExit || new require('./lib/gracefulexit')(_self.config);
	_self.config.sendMessage = _self.config.sendMessage || new require('./lib/sendmessage')(_self.config);
	_self.config.startup = _self.config.startup || new require('./lib/startup')(_self.config);
	_self.config.shutdown = _self.config.shutdown || new require('./lib/shutdown')(_self.config);

	if(userConfig && userConfig.extendFirestarter) userConfig.extendFirestarter(_self.config);

	process.on('uncaughtException', function(err) {
	    _self.config.logger.info('Uncaught Exception: '+err);
	    _self.config.logger.info(err.stack);
	    _self.config.sendMessage('offline');
		_self.config.shutdown(null, true);
	});

	process.on('message', function(message) {
		if (message === 'ping') {
			_self.config.sendMessage('pong');
		} else if (message === 'shutdown') {
			_self.config.logger.info('Received shutdown message from process instanciator');
			_self.config.sendMessage('offline');
			_self.config.shutdown(null, true);process.on('SIGINT', function() {
		_self.config.logger.info('');
		_self.config.logger.info('Received shutdown message from SIGINT (ctrl+c)');
		_self.config.sendMessage('offline');
		_self.config.shutdown(null, true);
	});
		}
	});

	if(!_self.config.serverDomain) _self.config.serverDomain = _self.config.domain.create();

	_self.config.serverDomain.on('error', function(err){
		_self.config.sendMessage('offline');
		_self.config.logger.info('Domain Error: '+err);
	    _self.config.logger.info(err.stack);
	    _self.config.shutdown(null, true);
	});

	return {

		config : _self.config

	  , shutdown : _self.config.shutdown

	  , startup : _self.config.startup

	  , getApp : function(){

			return _self.config.app;
		}

	  , getServer : function(){

			return _self.config.server;
		}

	  , getHttp : function(){

			return _self.config.http;
		}

	  , getServerDomain : function(){

			return _self.config.serverDomain;
		}
	};
};
<|endoftext|>


<commit_before>var _ = require('lodash');

var React = require('react');
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;

var MessageActionCreators = require('../../actions/MessageActionCreators');
var TypingActionCreators = require('../../actions/TypingActionCreators');

var ENTER_KEY_CODE = 13;

var ComposeSection = React.createClass({
  mixins: [PureRenderMixin],

  propTypes: {
    dialog: React.PropTypes.object.isRequired
  },

  getInitialState: function() {
    return({
      text: ''
    });
  },

  render: function() {
    return (

        <textarea className="compose__message" value={this.state.text} onChange={this._onChange} onKeyDown={this._onKeyDown}></textarea>

          <button className="button" onClick={this._onSendFileClick}>
             Send file
          </button>
          <button className="button" onClick={this._onSendPhotoClick}>
             Send photo
          </button>

          <button className="button button--primary">Send</button>

          <input type="file"
                 id="composeFileInput"
                 onChange={this._onFileInputChange}/>
          <input type="file"
                 id="composePhotoInput"
                 onChange={this._onPhotoInputChange}/>

    )
  },

  _onChange: function(event) {
    TypingActionCreators.onTyping(this.props.dialog.peer.peer);
    this.setState({text: event.target.value});
  },

  _onKeyDown: function(event) {
    if (event.keyCode === ENTER_KEY_CODE) {
      event.preventDefault();
      var text = this.state.text;
      if (text) {
        MessageActionCreators.sendTextMessage(this.props.dialog, text);
      }
      this.setState({text: ''});
    }
  },

  _onSendFileClick: function() {
    var fileInput = document.getElementById('composeFileInput');
    fileInput.click();
  },

  _onSendPhotoClick: function() {
    var photoInput = document.getElementById('composePhotoInput');
    photoInput.accept = "image/*";
    photoInput.click();
  },

  _onFileInputChange: function() {
    var files = document.getElementById('composeFileInput').files;
    MessageActionCreators.sendFileMessage(this.props.dialog, files[0]);
  },

  _onPhotoInputChange: function() {
    var photos = document.getElementById('composePhotoInput').files;
    console.warn("files", photos[0]);
    MessageActionCreators.sendPhotoMessage(this.props.dialog, photos[0]);
  },

  _onPaste: function(event) {
    var preventDefault = false;

    _.forEach(event.clipboardData.items, function(item) {
      if (item.type.indexOf('image') != -1) {
        preventDefault = true;
        MessageActionCreators.sendPhotoMessage(this.props.dialog, item.getAsFile());
      }
    }, this);

    if (preventDefault) {
      event.preventDefault();
    }
  }
});

module.exports = ComposeSection;
<commit_msg>feat(web): ability to compose multi-line messages<commit_after>var _ = require('lodash');

var React = require('react');
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;

var MessageActionCreators = require('../../actions/MessageActionCreators');
var TypingActionCreators = require('../../actions/TypingActionCreators');

var ENTER_KEY_CODE = 13;

var ComposeSection = React.createClass({
  mixins: [PureRenderMixin],

  propTypes: {
    dialog: React.PropTypes.object.isRequired
  },

  getInitialState: function() {
    return({
      text: ''
    });
  },

  render: function() {
    return (

        <textarea className="compose__message" value={this.state.text} onChange={this._onChange} onKeyDown={this._onKeyDown}></textarea>

          <button className="button" onClick={this._onSendFileClick}>
             Send file
          </button>
          <button className="button" onClick={this._onSendPhotoClick}>
             Send photo
          </button>

          <button className="button button--primary">Send</button>

          <input type="file"
                 id="composeFileInput"
                 onChange={this._onFileInputChange}/>
          <input type="file"
                 id="composePhotoInput"
                 onChange={this._onPhotoInputChange}/>

    )
  },

  _onChange: function(event) {
    TypingActionCreators.onTyping(this.props.dialog.peer.peer);
    this.setState({text: event.target.value});
  },

  _onKeyDown: function(event) {
    if (event.keyCode === ENTER_KEY_CODE && !event.shiftKey) {
      event.preventDefault();
      var text = this.state.text;
      if (text) {
        MessageActionCreators.sendTextMessage(this.props.dialog, text);
      }
      this.setState({text: ''});
    }
  },

  _onSendFileClick: function() {
    var fileInput = document.getElementById('composeFileInput');
    fileInput.click();
  },

  _onSendPhotoClick: function() {
    var photoInput = document.getElementById('composePhotoInput');
    photoInput.accept = "image/*";
    photoInput.click();
  },

  _onFileInputChange: function() {
    var files = document.getElementById('composeFileInput').files;
    MessageActionCreators.sendFileMessage(this.props.dialog, files[0]);
  },

  _onPhotoInputChange: function() {
    var photos = document.getElementById('composePhotoInput').files;
    MessageActionCreators.sendPhotoMessage(this.props.dialog, photos[0]);
  },

  _onPaste: function(event) {
    var preventDefault = false;

    _.forEach(event.clipboardData.items, function(item) {
      if (item.type.indexOf('image') != -1) {
        preventDefault = true;
        MessageActionCreators.sendPhotoMessage(this.props.dialog, item.getAsFile());
      }
    }, this);

    if (preventDefault) {
      event.preventDefault();
    }
  }
});

module.exports = ComposeSection;
<|endoftext|>


<commit_before>// module:
//		dui/tests/boilerplate
// description:
//		A <script src="boilerplate.js"> on your test page will:
//
//		- load claro or a specified theme
//		- load the loader (i.e. define the require() method)
//
//		By URL flags you can specify the theme,
//		and optionally enable RTL (right to left) mode, and/or dj_a11y (high-
//		contrast/image off emulation) ... probably not a genuine test for a11y.
//
//		You should NOT be using this in a production environment.  Rather, load
//		the AMD loader directly, for example:
//
//		<script src="requirejs/require.js">

// Parse the URL, get parameters
var dir = "",
	testMode = null,
	locale;
if (window.location.href.indexOf("?") > -1) {
	var str = window.location.href.substr(window.location.href.indexOf("?") + 1).split(/#/);
	var ary = str[0].split(/&/);
	for (var i = 0; i < ary.length; i++) {
		var split = ary[i].split("="),
			key = split[0],
			value = (split[1] || '').replace(/[^\w]/g, "");	// replace() to prevent XSS attack
		switch (key) {
		case "locale":
			// locale string | null
			locale = value;
			break;
		case "dir":
			// rtl | null
			dir = value;
			break;
		case "a11y":
			if (value) {
				testMode = "dj_a11y";
			}
			break;
		}
	}
}

// Find the <script src="boilerplate.js"> tag, to get test directory and data-dojo-config argument
var scripts = document.getElementsByTagName("script"), script, overrides = {};
for (i = 0; script = scripts[i]; i++) {
	var src = script.getAttribute("src"),
		match = src && src.match(/(.*|^)boilerplate\.js/i);
	if (match) {
		// Sniff location of dui/tests directory relative to this test file.   testDir will be an empty string if it's
		// the same directory, or a string including a slash, ex: "../", if the test is in a subdirectory.
		testDir = match[1];

		// Sniff configuration on attribute in script element.
		// Allows syntax like <script src="boilerplate.js data-dojo-config="parseOnLoad: true">, where the settings
		// specified override the default settings.
		var attr = script.getAttribute("data-dojo-config");
		if (attr) {
			overrides = eval("({ " + attr + " })");
		}
		break;
	}
}

// Setup configuration options for the loader
require = {
	baseUrl: testDir + "../../",
	packages: [
		{name: 'dcl', location: 'dcl'},
		{name: 'dojo', location: 'dojo'},
		{name: 'dui', location: 'dui'},
		{name: 'dojox', location: 'dojox'},
		{name: 'doh', location: 'util/doh'}
	],
	locale: locale || "en-us",
	config: {
		'dojo/has': {
			'dojo-bidi': dir == "rtl"
		}
	}
};
for (var key in overrides) {
	require[key] = overrides[key];
}

// Output the boilerplate text to load the loader.
document.write('<script type="text/javascript" src="' + testDir + '../../requirejs/require.js"></script>');

// On IE9 the following inlined script will run before dojo has finished loading, leading to an error because require()
// isn't defined yet.  Workaround it by putting the code in a separate file.
//document.write('<script type="text/javascript">require(["dojo/domReady!"], boilerplateOnLoad);</script>');
document.write('<script type="text/javascript" src="' + testDir + 'boilerplateOnload.js"></script>');

function boilerplateOnLoad() {
	// This function is the first registered domReady() callback.

	// a11y (flag for faux high-contrast testing)
	if (testMode) {
		document.body.className += " " + testMode;
	}

	// BIDI
	if (dir == "rtl") {
		// set dir=rtl on <html> node
		document.body.parentNode.setAttribute("dir", "rtl");

		require(["dojo/query!css2", "dojo/NodeList-dom"], function (query) {
			// pretend all the labels are in an RTL language, because
			// that affects how they lay out relative to inline form widgets
			query("label").attr("dir", "rtl");
		});
	}

	// parseOnLoad: true requires that the parser itself be loaded.
	if (require.parseOnLoad) {
		require(["dojo/parser"]);
	}
}
<commit_msg>remove call to old dojo/parser and update doc<commit_after>// module:
//		dui/tests/boilerplate
// description:
//		A <script src="boilerplate.js"> on your test page will
//		load the loader (i.e. define the require() method)
//
//		In addition, by URL flags you can specify the theme,
//		and optionally enable RTL (right to left) mode, and/or dj_a11y (high-
//		contrast/image off emulation) ... probably not a genuine test for a11y.
//
//		You should NOT be using this in a production environment.  Rather, load
//		the AMD loader directly, for example:
//
//		<script src="requirejs/require.js">

// Parse the URL, get parameters
var dir = "",
	testMode = null,
	locale;
if (window.location.href.indexOf("?") > -1) {
	var str = window.location.href.substr(window.location.href.indexOf("?") + 1).split(/#/);
	var ary = str[0].split(/&/);
	for (var i = 0; i < ary.length; i++) {
		var split = ary[i].split("="),
			key = split[0],
			value = (split[1] || '').replace(/[^\w]/g, "");	// replace() to prevent XSS attack
		switch (key) {
		case "locale":
			// locale string | null
			locale = value;
			break;
		case "dir":
			// rtl | null
			dir = value;
			break;
		case "a11y":
			if (value) {
				testMode = "dj_a11y";
			}
			break;
		}
	}
}

// Find the <script src="boilerplate.js"> tag, to get test directory and data-dojo-config argument
var scripts = document.getElementsByTagName("script"), script, overrides = {};
for (i = 0; script = scripts[i]; i++) {
	var src = script.getAttribute("src"),
		match = src && src.match(/(.*|^)boilerplate\.js/i);
	if (match) {
		// Sniff location of dui/tests directory relative to this test file.   testDir will be an empty string if it's
		// the same directory, or a string including a slash, ex: "../", if the test is in a subdirectory.
		testDir = match[1];

		// Sniff configuration on attribute in script element.
		// Allows syntax like <script src="boilerplate.js data-dojo-config="parseOnLoad: true">, where the settings
		// specified override the default settings.
		var attr = script.getAttribute("data-dojo-config");
		if (attr) {
			overrides = eval("({ " + attr + " })");
		}
		break;
	}
}

// Setup configuration options for the loader
require = {
	baseUrl: testDir + "../../",
	packages: [
		{name: 'dcl', location: 'dcl'},
		{name: 'dojo', location: 'dojo'},
		{name: 'dui', location: 'dui'},
		{name: 'dojox', location: 'dojox'},
		{name: 'doh', location: 'util/doh'}
	],
	locale: locale || "en-us",
	config: {
		'dojo/has': {
			'dojo-bidi': dir == "rtl"
		}
	}
};
for (var key in overrides) {
	require[key] = overrides[key];
}

// Output the boilerplate text to load the loader.
document.write('<script type="text/javascript" src="' + testDir + '../../requirejs/require.js"></script>');

// On IE9 the following inlined script will run before dojo has finished loading, leading to an error because require()
// isn't defined yet.  Workaround it by putting the code in a separate file.
//document.write('<script type="text/javascript">require(["dojo/domReady!"], boilerplateOnLoad);</script>');
document.write('<script type="text/javascript" src="' + testDir + 'boilerplateOnload.js"></script>');

function boilerplateOnLoad() {
	// This function is the first registered domReady() callback.

	// a11y (flag for faux high-contrast testing)
	if (testMode) {
		document.body.className += " " + testMode;
	}

	// BIDI
	if (dir == "rtl") {
		// set dir=rtl on <html> node
		document.body.parentNode.setAttribute("dir", "rtl");

		require(["dojo/query!css2", "dojo/NodeList-dom"], function (query) {
			// pretend all the labels are in an RTL language, because
			// that affects how they lay out relative to inline form widgets
			query("label").attr("dir", "rtl");
		});
	}
}
<|endoftext|>


<commit_before>'use strict';

var BrowserWindow  = require('browser-window')
var globalShortcut = require('global-shortcut')
var Menu           = require('menu')

var url            = require('url')
var querystring    = require('querystring')

var config         = require('./lib/config')

var menubar        = require('menubar')
var mb             = menubar({
  icon          : __dirname + '/app/IconTemplate.png',
  dir           : __dirname + '/app',
  preloadWindow : true, // TODO: enable if already logged in
  width         : 400,
  height        : 500,
  resizable     : false
})

var debug = process.env.NODE_ENV === 'development'

/**
 * Window references
 */
var debugWindow = null

mb.on('ready', function() {

  Menu.setApplicationMenu(require('./lib/menu'));

  if (debug)
    debugWindow = new BrowserWindow({
      width  : 995,
      height : 600,
      type   : 'desktop',
      frame  : true
    })

  function doLogin() {
    mb.window.loadUrl('https://soundcloud.com/connect?client_id=f17c1d67b83c86194fad2b1948061c9e&response_type=token&scope=non-expiring&display=next&redirect_uri=cumulus://oauth/callback')
  }

  function initialize() {

    if (debug) {
      debugWindow.openDevTools()
      debugWindow.loadUrl('file://' + __dirname + '/app/index.html')
    }

    mb.window.setSize(320, 500)
    mb.window.setMaximumSize(320, 600)
    mb.window.setMinimumSize(320, 400)
    mb.window.setResizable(true)
    mb.window.loadUrl('file://' + __dirname + '/app/index.html')
    mb.window.on('focus', function() { _sendWindowEvent('focus') })
  }

  /**
   * register Cumulus protocol
   */
  var protocol = require('protocol')
  protocol.registerHttpProtocol('cumulus', function(req) {

    // parse access token
    var hash  = url.parse(req.url).hash.substr(1)
    var token = querystring.parse(hash).access_token

    config.set('access_token', token, function(err) {
      if (err)
        throw err
      else
        initialize()
    })

  })

  // check if we already have an access_token
  config.get('access_token', function(err, value) {
    if (err)
      throw err

    if (typeof value !== 'undefined')
      initialize()
    else
      doLogin()
  })

  function _sendGlobalShortcut(accelerator) {
    if (!mb.window) return
    mb.window.webContents.send('GlobalShortcuts', accelerator)
  }

  function _sendWindowEvent(name) {
    if (!mb.window) return
    mb.window.webContents.send('WindowEvent', name)
  }

  globalShortcut.register('MediaPlayPause', function() {
    _sendGlobalShortcut('MediaPlayPause')
  })

  globalShortcut.register('MediaNextTrack', function() {
    _sendGlobalShortcut('MediaNextTrack')
  })

  globalShortcut.register('MediaPreviousTrack', function() {
    _sendGlobalShortcut('MediaPreviousTrack')
  })

})
<commit_msg>Login window should not use node-integration. Fixes #15.<commit_after>'use strict';

var BrowserWindow  = require('browser-window')
var globalShortcut = require('global-shortcut')
var Menu           = require('menu')

var url            = require('url')
var querystring    = require('querystring')

var config         = require('./lib/config')

var menubar        = require('menubar')
var mb             = menubar({
  icon          : __dirname + '/app/IconTemplate.png',
  dir           : __dirname + '/app',
  preloadWindow : true, // TODO: enable if already logged in
  width         : 400,
  height        : 500,
  resizable     : false
})

var debug = process.env.NODE_ENV === 'development'

/**
 * Window references
 */
var debugWindow, loginWindow

mb.on('ready', function() {

  Menu.setApplicationMenu(require('./lib/menu'));

  if (debug)
    debugWindow = new BrowserWindow({
      width  : 995,
      height : 600,
      type   : 'desktop',
      frame  : true
    })

  function doLogin() {
    loginWindow = new BrowserWindow({
      width: 400,
      height: 500,
      resizable: false,
      'node-integration': false
    })
    loginWindow.loadUrl('https://soundcloud.com/connect?client_id=f17c1d67b83c86194fad2b1948061c9e&response_type=token&scope=non-expiring&display=next&redirect_uri=cumulus://oauth/callback')
  }

  function initialize() {

    if (debug) {
      debugWindow.openDevTools()
      debugWindow.loadUrl('file://' + __dirname + '/app/index.html')
    }

    mb.window.setSize(320, 500)
    mb.window.setMaximumSize(320, 600)
    mb.window.setMinimumSize(320, 400)
    mb.window.setResizable(true)
    mb.window.loadUrl('file://' + __dirname + '/app/index.html')
    mb.window.on('focus', function() { _sendWindowEvent('focus') })
  }

  /**
   * register Cumulus protocol
   */
  var protocol = require('protocol')
  protocol.registerHttpProtocol('cumulus', function(req) {

    // parse access token
    var hash  = url.parse(req.url).hash.substr(1)
    var token = querystring.parse(hash).access_token

    config.set('access_token', token, function(err) {
      if (err) throw err
      if (loginWindow) loginWindow.close()
      initialize()
    })

  })

  // check if we already have an access_token
  config.get('access_token', function(err, value) {
    if (err)
      throw err

    if (typeof value !== 'undefined')
      initialize()
    else
      doLogin()
  })

  function _sendGlobalShortcut(accelerator) {
    if (!mb.window) return
    mb.window.webContents.send('GlobalShortcuts', accelerator)
  }

  function _sendWindowEvent(name) {
    if (!mb.window) return
    mb.window.webContents.send('WindowEvent', name)
  }

  globalShortcut.register('MediaPlayPause', function() {
    _sendGlobalShortcut('MediaPlayPause')
  })

  globalShortcut.register('MediaNextTrack', function() {
    _sendGlobalShortcut('MediaNextTrack')
  })

  globalShortcut.register('MediaPreviousTrack', function() {
    _sendGlobalShortcut('MediaPreviousTrack')
  })

})
<|endoftext|>


<commit_before>/*
 *
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

/**
 *  DocumentHolder.js
 *  Document Editor
 *
 *  Created by Alexander Yuzhin on 11/8/16
 *  Copyright (c) 2018 Ascensio System SIA. All rights reserved.
 *
 */

define([
    'core',
    'jquery',
    'underscore',
    'backbone',
    'documenteditor/mobile/app/view/DocumentHolder',
    'common/main/lib/collection/Users'
], function (core, $, _, Backbone) {
    'use strict';

    DE.Controllers.DocumentHolder = Backbone.Controller.extend(_.extend((function() {
        // private
        var _stack,
            _view,
            _fastCoAuthTips = [],
            _actionSheets = [],
            _isEdit = false,
            _canAcceptChanges = false,
            _inRevisionChange = false,
            _menuPos = [];

        return {
            models: [],
            collections: [
                'Common.Collections.Users'
            ],
            views: [
                'DocumentHolder'
            ],

            initialize: function() {
                this.addListeners({
                    'DocumentHolder': {
                        'contextmenu:click' : this.onContextMenuClick
                    }
                });
            },

            setApi: function(api) {
                var me = this;

                me.api = api;

                me.api.asc_registerCallback('asc_onShowPopMenu',            _.bind(me.onApiShowPopMenu, me));
                me.api.asc_registerCallback('asc_onHidePopMenu',            _.bind(me.onApiHidePopMenu, me));
                me.api.asc_registerCallback('asc_onShowForeignCursorLabel', _.bind(me.onApiShowForeignCursorLabel, me));
                me.api.asc_registerCallback('asc_onHideForeignCursorLabel', _.bind(me.onApiHideForeignCursorLabel, me));
                me.api.asc_registerCallback('asc_onAuthParticipantsChanged',_.bind(me.onApiUsersChanged, me));
                me.api.asc_registerCallback('asc_onConnectionStateChanged', _.bind(me.onApiUserConnection, me));
                me.api.asc_registerCallback('asc_onDocumentContentReady',   _.bind(me.onApiDocumentContentReady, me));
                Common.NotificationCenter.on('api:disconnect',              _.bind(me.onCoAuthoringDisconnect, me));
                me.api.asc_registerCallback('asc_onCoAuthoringDisconnect',  _.bind(me.onCoAuthoringDisconnect,me));
                me.api.asc_registerCallback('asc_onShowRevisionsChange',    _.bind(me.onApiShowChange, me));
                me.api.asc_coAuthoringGetUsers();
            },

            setMode: function (mode) {
                _isEdit = mode.isEdit;
                _canAcceptChanges = mode.canReview && !mode.isReviewOnly;
            },

            // When our application is ready, lets get started
            onLaunch: function() {
                var me = this;

                _view = me.createView('DocumentHolder').render();

                $$(window).on('resize', _.bind(me.onEditorResize, me));
            },

            // Handlers

            onContextMenuClick: function (view, eventName) {
                var me = this;

                if ('cut' == eventName) {
                    me.api.Cut();
                } else if ('copy' == eventName) {
                    me.api.Copy();
                } else if ('paste' == eventName) {
                    me.api.Paste();
                } else if ('delete' == eventName) {
                    me.api.asc_Remove();
                } else if ('edit' == eventName) {
                    _view.hideMenu();

                    DE.getController('EditContainer').showModal();
                } else if ('addlink' == eventName) {
                    _view.hideMenu();

                    DE.getController('AddContainer').showModal();
                    DE.getController('AddOther').getView('AddOther').showLink(false);
                } else if ('openlink' == eventName) {
                    _.some(_stack, function (item) {
                        if (item.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
                            me._openLink(item.get_ObjectValue().get_Value());
                            return true;
                        }
                    });
                } else if ('accept' == eventName) {
                    me.api.asc_GetNextRevisionsChange();
                    me.api.asc_AcceptChanges();
                } else if ('acceptall' == eventName) {
                    me.api.asc_AcceptAllChanges();
                } else if ('reject' == eventName) {
                    me.api.asc_GetNextRevisionsChange();
                    me.api.asc_RejectChanges();
                } else if ('rejectall' == eventName) {
                    me.api.asc_RejectAllChanges();
                } else if ('review' == eventName) {
                    if (Common.SharedSettings.get('phone')) {
                        _actionSheets = me._initReviewMenu();
                            me.onContextMenuClick(view, 'showActionSheet');
                    } else {
                        _.delay(function () {
                            _view.showMenu(me._initReviewMenu(), _menuPos[0] || 0, _menuPos[1] || 0);
                        }, 100);
                    }
                } else if ('showActionSheet' == eventName && _actionSheets.length > 0) {
                    _.delay(function () {
                        _.each(_actionSheets, function (action) {
                            action.text = action.caption;
                            action.onClick = function () {
                                me.onContextMenuClick(null, action.event)
                            }
                        });

                        uiApp.actions([_actionSheets, [
                            {
                                text: me.sheetCancel,
                                bold: true
                            }
                        ]]);
                    }, 100);
                }

                _view.hideMenu();
            },

            // API Handlers

            onEditorResize: function(cmp) {
                // Hide context menu
            },

            onApiShowPopMenu: function(posX, posY) {
                if ($('.popover.settings, .popup.settings, .picker-modal.settings, .modal.modal-in, .actions-modal').length > 0) {
                    return;
                }
                _menuPos = [posX, posY];

                var me = this,
                    items;

                _stack = me.api.getSelectedElements();
                items = me._initMenu(_stack);

                _view.showMenu(items, posX, posY);
            },

            onApiHidePopMenu: function() {
                _view && _view.hideMenu();
            },

            onApiShowForeignCursorLabel: function(userId, X, Y, color) {
                var me = this,
                    tipHeight = 20;

                var getUserName = function(id) {
                    var usersStore = DE.getCollection('Common.Collections.Users');

                    if (usersStore){
                        var rec = usersStore.findUser(id);
                        if (rec)
                            return rec.get('username');
                    }
                    return me.textGuest;
                };

                /** coauthoring begin **/
                var src = _.find(_fastCoAuthTips, function(tip){ return tip.attr('userid') == userId; });

                if (!src) {
                    src = $(document.createElement('div'));
                    src.addClass('username-tip');
                    src.attr('userid', userId);
                    src.css({
                        height: tipHeight + 'px',
                        position: 'absolute',
                        zIndex: '900',
                        display: 'none',
                        'pointer-events': 'none',
                        'background-color': '#' + Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b())});
                    src.text(getUserName(userId));
                    $('#id_main_view').append(src);

                    _fastCoAuthTips.push(src);

                    src.fadeIn(150);
                }
                src.css({
                    top: (Y - tipHeight) + 'px',
                    left: X + 'px'});
                /** coauthoring end **/
            },

            onApiHideForeignCursorLabel: function(userId) {
                /** coauthoring begin **/
                for (var i=0; i<_fastCoAuthTips.length; i++) {
                    if (_fastCoAuthTips[i].attr('userid') == userId) {
                        var src = _fastCoAuthTips[i];
                        _fastCoAuthTips[i].fadeOut(150, function(){src.remove()});
                        _fastCoAuthTips.splice(i, 1);
                        break;
                    }
                }
                /** coauthoring end **/
            },

            onApiUsersChanged: function(users){
                var usersStore = this.getApplication().getCollection('Common.Collections.Users');

                if (usersStore) {
                    var arrUsers = [], name, user;

                    for (name in users) {
                        if (undefined !== name) {
                            user = users[name];
                            if (user) {
                                arrUsers.push(new Common.Models.User({
                                    id          : user.asc_getId(),
                                    username    : user.asc_getUserName(),
                                    online      : true,
                                    color       : user.asc_getColor(),
                                    view        : user.asc_getView()
                                }));
                            }
                        }
                    }

                    usersStore[usersStore.size() > 0 ? 'add' : 'reset'](arrUsers);
                }
            },

            onApiUserConnection: function(change){
                var usersStore = this.getApplication().getCollection('Common.Collections.Users');

                if (usersStore){
                    var user = usersStore.findUser(change.asc_getId());
                    if (!user) {
                        usersStore.add(new Common.Models.User({
                            id          : change.asc_getId(),
                            username    : change.asc_getUserName(),
                            online      : change.asc_getState(),
                            color       : change.asc_getColor(),
                            view        : change.asc_getView()
                        }));
                    } else {
                        user.set({online: change.asc_getState()});
                    }
                }
            },

            onApiDocumentContentReady: function () {
                _view = this.createView('DocumentHolder').render();
            },

            onApiShowChange: function(sdkchange) {
                _inRevisionChange = sdkchange && sdkchange.length>0;
            },

            // Internal

            _openLink: function(url) {
                if (this.api.asc_getUrlType(url) > 0) {
                    var newDocumentPage = window.open(url, '_blank');

                    if (newDocumentPage) {
                        newDocumentPage.focus();
                    }
                }
            },

            _initMenu: function (stack) {
                var me = this,
                    menuItems = [],
                    canCopy = me.api.can_CopyCut();

                _actionSheets = [];

                if (canCopy) {
                    menuItems.push({
                        caption: me.menuCopy,
                        event: 'copy'
                    });
                }

                var isText = false,
                    isTable = false,
                    isImage = false,
                    isChart = false,
                    isShape = false,
                    isLink = false;

                _.each(stack, function (item) {
                    var objectType = item.get_ObjectType(),
                        objectValue = item.get_ObjectValue();

                    if (objectType == Asc.c_oAscTypeSelectElement.Text) {
                        isText = true;
                    } else if (objectType == Asc.c_oAscTypeSelectElement.Image) {
                        if (objectValue && objectValue.get_ChartProperties()) {
                            isChart = true;
                        } else if (objectType && objectValue.get_ShapeProperties()) {
                            isShape = true;
                        } else {
                            isImage = true;
                        }
                    } else if (objectType == Asc.c_oAscTypeSelectElement.Table) {
                        isTable = true;
                    } else if (objectType == Asc.c_oAscTypeSelectElement.Hyperlink) {
                        isLink = true;
                    }
                });

                if (stack.length > 0) {
                    var topObject = _.find(stack.reverse(), function(obj){ return obj.get_ObjectType() != Asc.c_oAscTypeSelectElement.SpellCheck; }),
                        topObjectValue = topObject.get_ObjectValue(),
                        objectLocked = _.isFunction(topObjectValue.get_Locked) ? topObjectValue.get_Locked() : false;

                    var swapItems = function(items, indexBefore, indexAfter) {
                        items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0];
                    };

                    if (!objectLocked && _isEdit && !me.isDisconnected) {
                        if (canCopy) {
                            menuItems.push({
                                caption: me.menuCut,
                                event: 'cut'
                            });

                            // Swap 'Copy' and 'Cut'
                            swapItems(menuItems, 0, 1);
                        }

                        menuItems.push({
                            caption: me.menuPaste,
                            event: 'paste'
                        });

                        menuItems.push({
                            caption: me.menuDelete,
                            event: 'delete'
                        });

                        menuItems.push({
                            caption: me.menuEdit,
                            event: 'edit'
                        });

                        if (!_.isEmpty(me.api.can_AddHyperlink())) {
                            menuItems.push({
                                caption: me.menuAddLink,
                                event: 'addlink'
                            });
                        }

                        if (_canAcceptChanges && _inRevisionChange) {
                            menuItems.push({
                                caption: me.menuReview,
                                event: 'review'
                            });
                        }
                    }
                }

                if (isLink) {
                    menuItems.push({
                        caption: me.menuOpenLink,
                        event: 'openlink'
                    });
                }

                if (Common.SharedSettings.get('phone') && menuItems.length > 3) {
                    _actionSheets = menuItems.slice(3);

                    menuItems = menuItems.slice(0, 3);
                    menuItems.push({
                        caption: me.menuMore,
                        event: 'showActionSheet'
                    });
                }

                return menuItems;
            },

            _initReviewMenu: function (stack) {
                var me = this,
                    menuItems = [];

                menuItems.push({
                    caption: me.menuAccept,
                    event: 'accept'
                });

                menuItems.push({
                    caption: me.menuReject,
                    event: 'reject'
                });

                menuItems.push({
                    caption: me.menuAcceptAll,
                    event: 'acceptall'
                });

                menuItems.push({
                    caption: me.menuRejectAll,
                    event: 'rejectall'
                });

                return menuItems;
            },

            onCoAuthoringDisconnect: function() {
                this.isDisconnected = true;
            },

            textGuest: 'Guest',
            menuCut: 'Cut',
            menuCopy: 'Copy',
            menuPaste: 'Paste',
            menuEdit: 'Edit',
            menuDelete: 'Delete',
            menuAddLink: 'Add Link',
            menuOpenLink: 'Open Link',
            menuMore: 'More',
            sheetCancel: 'Cancel',
            menuReview: 'Review',
            menuAccept: 'Accept',
            menuAcceptAll: 'Accept All',
            menuReject: 'Reject',
            menuRejectAll: 'Reject All'
        }
    })(), DE.Controllers.DocumentHolder || {}))
});<commit_msg>[DE mobile] Sailfish: show review menu<commit_after>/*
 *
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

/**
 *  DocumentHolder.js
 *  Document Editor
 *
 *  Created by Alexander Yuzhin on 11/8/16
 *  Copyright (c) 2018 Ascensio System SIA. All rights reserved.
 *
 */

define([
    'core',
    'jquery',
    'underscore',
    'backbone',
    'documenteditor/mobile/app/view/DocumentHolder',
    'common/main/lib/collection/Users'
], function (core, $, _, Backbone) {
    'use strict';

    DE.Controllers.DocumentHolder = Backbone.Controller.extend(_.extend((function() {
        // private
        var _stack,
            _view,
            _fastCoAuthTips = [],
            _actionSheets = [],
            _isEdit = false,
            _canAcceptChanges = false,
            _inRevisionChange = false,
            _menuPos = [],
            _timer = 0;

        return {
            models: [],
            collections: [
                'Common.Collections.Users'
            ],
            views: [
                'DocumentHolder'
            ],

            initialize: function() {
                this.addListeners({
                    'DocumentHolder': {
                        'contextmenu:click' : this.onContextMenuClick
                    }
                });
            },

            setApi: function(api) {
                var me = this;

                me.api = api;

                me.api.asc_registerCallback('asc_onShowPopMenu',            _.bind(me.onApiShowPopMenu, me));
                me.api.asc_registerCallback('asc_onHidePopMenu',            _.bind(me.onApiHidePopMenu, me));
                me.api.asc_registerCallback('asc_onShowForeignCursorLabel', _.bind(me.onApiShowForeignCursorLabel, me));
                me.api.asc_registerCallback('asc_onHideForeignCursorLabel', _.bind(me.onApiHideForeignCursorLabel, me));
                me.api.asc_registerCallback('asc_onAuthParticipantsChanged',_.bind(me.onApiUsersChanged, me));
                me.api.asc_registerCallback('asc_onConnectionStateChanged', _.bind(me.onApiUserConnection, me));
                me.api.asc_registerCallback('asc_onDocumentContentReady',   _.bind(me.onApiDocumentContentReady, me));
                Common.NotificationCenter.on('api:disconnect',              _.bind(me.onCoAuthoringDisconnect, me));
                me.api.asc_registerCallback('asc_onCoAuthoringDisconnect',  _.bind(me.onCoAuthoringDisconnect,me));
                me.api.asc_registerCallback('asc_onShowRevisionsChange',    _.bind(me.onApiShowChange, me));
                me.api.asc_coAuthoringGetUsers();
            },

            setMode: function (mode) {
                _isEdit = mode.isEdit;
                _canAcceptChanges = mode.canReview && !mode.isReviewOnly;
            },

            // When our application is ready, lets get started
            onLaunch: function() {
                var me = this;

                _view = me.createView('DocumentHolder').render();

                $$(window).on('resize', _.bind(me.onEditorResize, me));
            },

            // Handlers

            onContextMenuClick: function (view, eventName) {
                var me = this;

                if ('cut' == eventName) {
                    me.api.Cut();
                } else if ('copy' == eventName) {
                    me.api.Copy();
                } else if ('paste' == eventName) {
                    me.api.Paste();
                } else if ('delete' == eventName) {
                    me.api.asc_Remove();
                } else if ('edit' == eventName) {
                    _view.hideMenu();

                    DE.getController('EditContainer').showModal();
                } else if ('addlink' == eventName) {
                    _view.hideMenu();

                    DE.getController('AddContainer').showModal();
                    DE.getController('AddOther').getView('AddOther').showLink(false);
                } else if ('openlink' == eventName) {
                    _.some(_stack, function (item) {
                        if (item.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
                            me._openLink(item.get_ObjectValue().get_Value());
                            return true;
                        }
                    });
                } else if ('accept' == eventName) {
                    me.api.asc_GetNextRevisionsChange();
                    me.api.asc_AcceptChanges();
                } else if ('acceptall' == eventName) {
                    me.api.asc_AcceptAllChanges();
                } else if ('reject' == eventName) {
                    me.api.asc_GetNextRevisionsChange();
                    me.api.asc_RejectChanges();
                } else if ('rejectall' == eventName) {
                    me.api.asc_RejectAllChanges();
                } else if ('review' == eventName) {
                    if (Common.SharedSettings.get('phone')) {
                        _actionSheets = me._initReviewMenu();
                        me.onContextMenuClick(view, 'showActionSheet');
                    } else {
                        _.delay(function () {
                            _view.showMenu(me._initReviewMenu(), _menuPos[0] || 0, _menuPos[1] || 0);
                            _timer = (new Date).getTime();
                        }, 100);
                    }
                } else if ('showActionSheet' == eventName && _actionSheets.length > 0) {
                    _.delay(function () {
                        _.each(_actionSheets, function (action) {
                            action.text = action.caption;
                            action.onClick = function () {
                                me.onContextMenuClick(null, action.event)
                            }
                        });

                        uiApp.actions([_actionSheets, [
                            {
                                text: me.sheetCancel,
                                bold: true
                            }
                        ]]);
                    }, 100);
                }

                _view.hideMenu();
            },

            // API Handlers

            onEditorResize: function(cmp) {
                // Hide context menu
            },

            onApiShowPopMenu: function(posX, posY) {
                if ($('.popover.settings, .popup.settings, .picker-modal.settings, .modal.modal-in, .actions-modal').length > 0) {
                    return;
                }
                var now = (new Date).getTime();
                if (now - _timer < 1000) return;
                _timer = 0;

                _menuPos = [posX, posY];

                var me = this,
                    items;

                _stack = me.api.getSelectedElements();
                items = me._initMenu(_stack);

                _view.showMenu(items, posX, posY);
            },

            onApiHidePopMenu: function() {
                _view && _view.hideMenu();
            },

            onApiShowForeignCursorLabel: function(userId, X, Y, color) {
                var me = this,
                    tipHeight = 20;

                var getUserName = function(id) {
                    var usersStore = DE.getCollection('Common.Collections.Users');

                    if (usersStore){
                        var rec = usersStore.findUser(id);
                        if (rec)
                            return rec.get('username');
                    }
                    return me.textGuest;
                };

                /** coauthoring begin **/
                var src = _.find(_fastCoAuthTips, function(tip){ return tip.attr('userid') == userId; });

                if (!src) {
                    src = $(document.createElement('div'));
                    src.addClass('username-tip');
                    src.attr('userid', userId);
                    src.css({
                        height: tipHeight + 'px',
                        position: 'absolute',
                        zIndex: '900',
                        display: 'none',
                        'pointer-events': 'none',
                        'background-color': '#' + Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b())});
                    src.text(getUserName(userId));
                    $('#id_main_view').append(src);

                    _fastCoAuthTips.push(src);

                    src.fadeIn(150);
                }
                src.css({
                    top: (Y - tipHeight) + 'px',
                    left: X + 'px'});
                /** coauthoring end **/
            },

            onApiHideForeignCursorLabel: function(userId) {
                /** coauthoring begin **/
                for (var i=0; i<_fastCoAuthTips.length; i++) {
                    if (_fastCoAuthTips[i].attr('userid') == userId) {
                        var src = _fastCoAuthTips[i];
                        _fastCoAuthTips[i].fadeOut(150, function(){src.remove()});
                        _fastCoAuthTips.splice(i, 1);
                        break;
                    }
                }
                /** coauthoring end **/
            },

            onApiUsersChanged: function(users){
                var usersStore = this.getApplication().getCollection('Common.Collections.Users');

                if (usersStore) {
                    var arrUsers = [], name, user;

                    for (name in users) {
                        if (undefined !== name) {
                            user = users[name];
                            if (user) {
                                arrUsers.push(new Common.Models.User({
                                    id          : user.asc_getId(),
                                    username    : user.asc_getUserName(),
                                    online      : true,
                                    color       : user.asc_getColor(),
                                    view        : user.asc_getView()
                                }));
                            }
                        }
                    }

                    usersStore[usersStore.size() > 0 ? 'add' : 'reset'](arrUsers);
                }
            },

            onApiUserConnection: function(change){
                var usersStore = this.getApplication().getCollection('Common.Collections.Users');

                if (usersStore){
                    var user = usersStore.findUser(change.asc_getId());
                    if (!user) {
                        usersStore.add(new Common.Models.User({
                            id          : change.asc_getId(),
                            username    : change.asc_getUserName(),
                            online      : change.asc_getState(),
                            color       : change.asc_getColor(),
                            view        : change.asc_getView()
                        }));
                    } else {
                        user.set({online: change.asc_getState()});
                    }
                }
            },

            onApiDocumentContentReady: function () {
                _view = this.createView('DocumentHolder').render();
            },

            onApiShowChange: function(sdkchange) {
                _inRevisionChange = sdkchange && sdkchange.length>0;
            },

            // Internal

            _openLink: function(url) {
                if (this.api.asc_getUrlType(url) > 0) {
                    var newDocumentPage = window.open(url, '_blank');

                    if (newDocumentPage) {
                        newDocumentPage.focus();
                    }
                }
            },

            _initMenu: function (stack) {
                var me = this,
                    menuItems = [],
                    canCopy = me.api.can_CopyCut();

                _actionSheets = [];

                if (canCopy) {
                    menuItems.push({
                        caption: me.menuCopy,
                        event: 'copy'
                    });
                }

                var isText = false,
                    isTable = false,
                    isImage = false,
                    isChart = false,
                    isShape = false,
                    isLink = false;

                _.each(stack, function (item) {
                    var objectType = item.get_ObjectType(),
                        objectValue = item.get_ObjectValue();

                    if (objectType == Asc.c_oAscTypeSelectElement.Text) {
                        isText = true;
                    } else if (objectType == Asc.c_oAscTypeSelectElement.Image) {
                        if (objectValue && objectValue.get_ChartProperties()) {
                            isChart = true;
                        } else if (objectType && objectValue.get_ShapeProperties()) {
                            isShape = true;
                        } else {
                            isImage = true;
                        }
                    } else if (objectType == Asc.c_oAscTypeSelectElement.Table) {
                        isTable = true;
                    } else if (objectType == Asc.c_oAscTypeSelectElement.Hyperlink) {
                        isLink = true;
                    }
                });

                if (stack.length > 0) {
                    var topObject = _.find(stack.reverse(), function(obj){ return obj.get_ObjectType() != Asc.c_oAscTypeSelectElement.SpellCheck; }),
                        topObjectValue = topObject.get_ObjectValue(),
                        objectLocked = _.isFunction(topObjectValue.get_Locked) ? topObjectValue.get_Locked() : false;

                    var swapItems = function(items, indexBefore, indexAfter) {
                        items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0];
                    };

                    if (!objectLocked && _isEdit && !me.isDisconnected) {
                        if (canCopy) {
                            menuItems.push({
                                caption: me.menuCut,
                                event: 'cut'
                            });

                            // Swap 'Copy' and 'Cut'
                            swapItems(menuItems, 0, 1);
                        }

                        menuItems.push({
                            caption: me.menuPaste,
                            event: 'paste'
                        });

                        menuItems.push({
                            caption: me.menuDelete,
                            event: 'delete'
                        });

                        menuItems.push({
                            caption: me.menuEdit,
                            event: 'edit'
                        });

                        if (!_.isEmpty(me.api.can_AddHyperlink())) {
                            menuItems.push({
                                caption: me.menuAddLink,
                                event: 'addlink'
                            });
                        }

                        if (_canAcceptChanges && _inRevisionChange) {
                            menuItems.push({
                                caption: me.menuReview,
                                event: 'review'
                            });
                        }
                    }
                }

                if (isLink) {
                    menuItems.push({
                        caption: me.menuOpenLink,
                        event: 'openlink'
                    });
                }

                if (Common.SharedSettings.get('phone') && menuItems.length > 3) {
                    _actionSheets = menuItems.slice(3);

                    menuItems = menuItems.slice(0, 3);
                    menuItems.push({
                        caption: me.menuMore,
                        event: 'showActionSheet'
                    });
                }

                return menuItems;
            },

            _initReviewMenu: function (stack) {
                var me = this,
                    menuItems = [];

                menuItems.push({
                    caption: me.menuAccept,
                    event: 'accept'
                });

                menuItems.push({
                    caption: me.menuReject,
                    event: 'reject'
                });

                menuItems.push({
                    caption: me.menuAcceptAll,
                    event: 'acceptall'
                });

                menuItems.push({
                    caption: me.menuRejectAll,
                    event: 'rejectall'
                });

                return menuItems;
            },

            onCoAuthoringDisconnect: function() {
                this.isDisconnected = true;
            },

            textGuest: 'Guest',
            menuCut: 'Cut',
            menuCopy: 'Copy',
            menuPaste: 'Paste',
            menuEdit: 'Edit',
            menuDelete: 'Delete',
            menuAddLink: 'Add Link',
            menuOpenLink: 'Open Link',
            menuMore: 'More',
            sheetCancel: 'Cancel',
            menuReview: 'Review',
            menuAccept: 'Accept',
            menuAcceptAll: 'Accept All',
            menuReject: 'Reject',
            menuRejectAll: 'Reject All'
        }
    })(), DE.Controllers.DocumentHolder || {}))
});<|endoftext|>