<commit_before>define(function (require, exports, module) {

    var ExtensionUtils = brackets.getModule("utils/ExtensionUtils"),
        NodeConnection = brackets.getModule("utils/NodeConnection");

    var Promise       = require("bluebird"),
        Strings       = require("strings"),
        ErrorHandler  = require("src/ErrorHandler"),
        ExpectedError = require("src/ExpectedError"),
        Preferences   = require("src/Preferences"),
        Utils         = require("src/Utils");

    var moduleDirectory   = ExtensionUtils.getModulePath(module),
        domainModulePath  = moduleDirectory + "domains/cli",
        debugOn           = Preferences.get("debugMode"),
        gitTimeout        = Preferences.get("gitTimeout") * 1000,
        domainName        = "brackets-git",
        nodeConnection    = new NodeConnection(),
        nextCliId         = 0,
        deferredMap       = {};

    // Constants
    var MAX_COUNTER_VALUE = 4294967295; // 2^32 - 1
    var EVENT_NAMESPACE   = ".bracketsGitEvent";

    function getNextCliId() {
        if (nextCliId >= MAX_COUNTER_VALUE) {
            nextCliId = 0;
        }
        return ++nextCliId;
    }

    function attachEventHandlers() {
        nodeConnection
            .off(EVENT_NAMESPACE)
            .on(domainName + ":progress" + EVENT_NAMESPACE, function (err, cliId, time, message) {
                var deferred = deferredMap[cliId];
                if (deferred && !deferred.isResolved()) {
                    deferred.progress(message);
                } else {
                    ErrorHandler.logError("Progress sent for a non-existing process(" + cliId + "): " + message);
                }
            });
    }

    var connectPromise = null;

    // return true/false to state if wasConnected before
    function connectToNode() {
        if (connectPromise) {
            return connectPromise;
        }

        connectPromise = new Promise(function (resolve, reject) {
            if (nodeConnection.connected()) {
                return resolve(true);
            }
            // we don't want automatic reconnections as we handle the reconnect manually
            nodeConnection.connect(false).then(function () {
                nodeConnection.loadDomains([domainModulePath], false).then(function () {
                    attachEventHandlers();
                    resolve(false);
                }).fail(function (err) { // jQuery promise - .fail is fine
                    reject(ErrorHandler.toError(err));
                });
            }).fail(function (err) { // jQuery promise - .fail is fine
                reject(ErrorHandler.toError(err));
            });
        });

        connectPromise.finally(function () {
            connectPromise = null;
        });

        return connectPromise;
    }

    function normalizePathForOs(path) {
        if (brackets.platform === "win") {
            path = path.replace(/\//g, "\\");
        }
        return path;
    }

    // this functions prevents sensitive info from going further (like http passwords)
    function sanitizeOutput(str) {
        if (typeof str !== "string") {
            if (str != null) { // checks for both null & undefined
                str = str.toString();
            } else {
                str = "";
            }
        }
        return str;
    }

    function logDebug(opts, debugInfo, method, type, out) {
        var processInfo = [];

        var duration = (new Date()).getTime() - debugInfo.startTime;
        processInfo.push(duration + "ms");

        if (!debugInfo.wasConnected) {
            processInfo.push("+conn");
        }

        if (opts.cliId) {
            processInfo.push("ID=" + opts.cliId);
        }

        var msg = "cmd-" + method + "-" + type + " (" + processInfo.join(";") + ")";
        if (out) { msg += ": \"" + out + "\""; }
        Utils.consoleDebug(msg);
    }

    function cliHandler(method, cmd, args, opts, retry) {
        var cliId     = getNextCliId(),
            deferred  = Promise.defer();

        deferredMap[cliId] = deferred;
        args = args || [];
        opts = opts || {};

        var watchProgress = args.indexOf("--progress") !== -1;

        // it is possible to set a custom working directory in options
        // otherwise the current project root is used to execute commands
        if (!opts.cwd) {
            opts.cwd = Preferences.get("currentGitRoot") || Utils.getProjectRoot();
        }

        // convert paths like c:/foo/bar to c:\foo\bar on windows
        opts.cwd = normalizePathForOs(opts.cwd);

        // log all cli communication into console when debug mode is on
        if (debugOn) {
            var startTime = (new Date()).getTime();
            Utils.consoleDebug("cmd-" + method + (watchProgress ? "-watch" : "") + ": " +
                               opts.cwd + " -> " +
                               cmd + " " + args.join(" "));
        }

        // we connect to node (promise is returned immediately if we are already connected)
        connectToNode().catch(function (err) {
            // failed to connect to node for some reason
            throw ErrorHandler.showError(new ExpectedError(err), Strings.ERROR_CONNECT_NODEJS);
        }).then(function (wasConnected) {

            var resolved      = false,
                timeoutLength = opts.timeout ? (opts.timeout * 1000) : gitTimeout;

            var domainOpts = {
                cliId: cliId,
                watchProgress: watchProgress
            };

            var debugInfo = {
                startTime: startTime,
                wasConnected: wasConnected
            };

            if (watchProgress) {
                deferred.progress("Running command: git " + args.join(" "));
            }

            // nodeConnection returns jQuery deferred
            nodeConnection.domains[domainName][method](opts.cwd, cmd, args, domainOpts)
                .fail(function (err) { // jQuery promise - .fail is fine
                    if (!resolved) {
                        err = sanitizeOutput(err);
                        if (debugOn) {
                            logDebug(domainOpts, debugInfo, method, "fail", err);
                        }
                        delete deferredMap[cliId];

                        err = ErrorHandler.toError(err);

                        // spawn ENOENT error
                        var invalidCwdErr = "spawn ENOENT";
                        if (err.stack && err.stack.indexOf(invalidCwdErr)) {
                            err.message = err.message.replace(invalidCwdErr, invalidCwdErr + " (" + opts.cwd + ")");
                            err.stack = err.stack.replace(invalidCwdErr, invalidCwdErr + " (" + opts.cwd + ")");
                        }

                        // socket was closed so we should try this once again (if not already retrying)
                        if (err.stack && err.stack.indexOf("WebSocket.self._ws.onclose") !== -1 && !retry) {
                            cliHandler(method, cmd, args, opts, true)
                                .then(function (response) {
                                    deferred.resolve(response);
                                })
                                .catch(function (err) {
                                    deferred.reject(err);
                                });
                            return;
                        }

                        deferred.reject(err);
                    }
                })
                .then(function (out) {
                    if (!resolved) {
                        out = sanitizeOutput(out);
                        if (debugOn) {
                            logDebug(domainOpts, debugInfo, method, "out", out);
                        }
                        delete deferredMap[cliId];
                        deferred.resolve(out);
                    }
                })
                .always(function () {
                    resolved = true;
                })
                .done();

            function timeoutPromise() {
                if (debugOn) {
                    logDebug(domainOpts, debugInfo, method, "timeout");
                }
                var err = new Error("cmd-" + method + "-timeout: " + cmd + " " + args.join(" "));
                if (!opts.timeoutExpected) {
                    ErrorHandler.logError(err);
                }

                // process still lives and we need to kill it
                nodeConnection.domains[domainName].kill(domainOpts.cliId)
                    .fail(function (err) {
                        ErrorHandler.logError(err);
                    });

                delete deferredMap[cliId];
                deferred.reject(ErrorHandler.toError(err));
                resolved = true;
            }

            var lastProgressTime = 0;
            function timeoutCall() {
                setTimeout(function () {
                    if (!resolved) {
                        if (typeof opts.timeoutCheck === "function") {
                            Promise.cast(opts.timeoutCheck())
                                .catch(function (err) {
                                    ErrorHandler.logError("timeoutCheck failed: " + opts.timeoutCheck.toString());
                                    ErrorHandler.logError(err);
                                })
                                .then(function (continueExecution) {
                                    if (continueExecution) {
                                        // check again later
                                        timeoutCall();
                                    } else {
                                        timeoutPromise();
                                    }
                                });
                        } else if (domainOpts.watchProgress) {
                            // we are watching the promise progress in the domain
                            // so we should check if the last message was sent in more than timeout time
                            var currentTime = (new Date()).getTime();
                            var diff = currentTime - lastProgressTime;
                            if (diff > timeoutLength) {
                                if (debugOn) {
                                    Utils.consoleDebug("cmd(" + cliId + ") - last progress message was sent " + diff + "ms ago - timeout");
                                }
                                timeoutPromise();
                            } else {
                                if (debugOn) {
                                    Utils.consoleDebug("cmd(" + cliId + ") - last progress message was sent " + diff + "ms ago - delay");
                                }
                                timeoutCall();
                            }
                        } else {
                            // we don't have any custom handler, so just kill the promise here
                            // note that command WILL keep running in the background
                            // so even when timeout occurs, operation might finish after it
                            timeoutPromise();
                        }
                    }
                }, timeoutLength);
            }

            // when opts.timeout === false then never timeout the process
            if (opts.timeout !== false) {
                // if we are watching for progress events, mark the time when last progress was made
                if (domainOpts.watchProgress) {
                    deferred.promise.progressed(function () {
                        lastProgressTime = (new Date()).getTime();
                    });
                }
                // call the method which will timeout the promise after a certain period of time
                timeoutCall();
            }

        }).catch(function (err) {
            throw ErrorHandler.showError(err, "Unexpected error in CLI handler - close all instances of Brackets and start again to reload");
        });

        return deferred.promise;
    }

    function which(cmd) {
        return cliHandler("which", cmd);
    }

    function pathExists(path) {
        return cliHandler("pathExists", path).then(function (response) {
            return typeof response === "string" ? response === "true" : response;
        });
    }

    function spawnCommand(cmd, args, opts) {
        return cliHandler("spawn", cmd, args, opts);
    }

    function executeCommand(cmd, args, opts) {
        return cliHandler("execute", cmd, args, opts);
    }

    // this is to be used together with executeCommand
    // spawnCommand does the escaping automatically
    function escapeShellArg(str) {
        if (typeof str !== "string") {
            throw new Error("escapeShellArg argument is not a string: " + typeof str);
        }
        if (str.length === 0) {
            return str;
        }
        if (brackets.platform !== "win") {
            // http://steve-parker.org/sh/escape.shtml
            str = str.replace(/["$`\\]/g, function (m) {
                return "\\" + m;
            });
            return "\"" + str + "\"";
        } else {
            // http://stackoverflow.com/questions/7760545/cmd-escape-double-quotes-in-parameter
            str = str.replace(/"/g, function () {
                return "\"\"\"";
            });
            return "\"" + str + "\"";
        }
    }

    // Public API
    exports.cliHandler      = cliHandler;
    exports.which           = which;
    exports.pathExists      = pathExists;
    exports.executeCommand  = executeCommand;
    exports.spawnCommand    = spawnCommand;
    exports.escapeShellArg  = escapeShellArg;

});
<commit_msg>try to connect again when getting Max connection attempts reached<commit_after>define(function (require, exports, module) {

    var ExtensionUtils = brackets.getModule("utils/ExtensionUtils"),
        NodeConnection = brackets.getModule("utils/NodeConnection");

    var Promise       = require("bluebird"),
        Strings       = require("strings"),
        ErrorHandler  = require("src/ErrorHandler"),
        ExpectedError = require("src/ExpectedError"),
        Preferences   = require("src/Preferences"),
        Utils         = require("src/Utils");

    var moduleDirectory   = ExtensionUtils.getModulePath(module),
        domainModulePath  = moduleDirectory + "domains/cli",
        debugOn           = Preferences.get("debugMode"),
        gitTimeout        = Preferences.get("gitTimeout") * 1000,
        domainName        = "brackets-git",
        nodeConnection    = new NodeConnection(),
        nextCliId         = 0,
        deferredMap       = {};

    // Constants
    var MAX_COUNTER_VALUE = 4294967295; // 2^32 - 1
    var EVENT_NAMESPACE   = ".bracketsGitEvent";

    function getNextCliId() {
        if (nextCliId >= MAX_COUNTER_VALUE) {
            nextCliId = 0;
        }
        return ++nextCliId;
    }

    function attachEventHandlers() {
        nodeConnection
            .off(EVENT_NAMESPACE)
            .on(domainName + ":progress" + EVENT_NAMESPACE, function (err, cliId, time, message) {
                var deferred = deferredMap[cliId];
                if (deferred && !deferred.isResolved()) {
                    deferred.progress(message);
                } else {
                    ErrorHandler.logError("Progress sent for a non-existing process(" + cliId + "): " + message);
                }
            });
    }

    var connectPromise = null;

    // return true/false to state if wasConnected before
    function connectToNode() {
        if (connectPromise) {
            return connectPromise;
        }

        connectPromise = new Promise(function (resolve, reject) {
            if (nodeConnection.connected()) {
                return resolve(true);
            }
            // we don't want automatic reconnections as we handle the reconnect manually
            nodeConnection.connect(false).then(function () {
                nodeConnection.loadDomains([domainModulePath], false).then(function () {
                    attachEventHandlers();
                    resolve(false);
                }).fail(function (err) { // jQuery promise - .fail is fine
                    reject(ErrorHandler.toError(err));
                });
            }).fail(function (err) { // jQuery promise - .fail is fine
                if (ErrorHandler.contains(err, "Max connection attempts reached")) {
                    Utils.consoleLog("Max connection attempts reached, trying again.", "warn");
                    // try again
                    connectPromise = null;
                    connectToNode()
                        .then(function (result) { resolve(result); })
                        .catch(function (err) { reject(err); });
                    return;
                }
                reject(ErrorHandler.toError(err));
            });
        });

        connectPromise.finally(function () {
            connectPromise = null;
        });

        return connectPromise;
    }

    function normalizePathForOs(path) {
        if (brackets.platform === "win") {
            path = path.replace(/\//g, "\\");
        }
        return path;
    }

    // this functions prevents sensitive info from going further (like http passwords)
    function sanitizeOutput(str) {
        if (typeof str !== "string") {
            if (str != null) { // checks for both null & undefined
                str = str.toString();
            } else {
                str = "";
            }
        }
        return str;
    }

    function logDebug(opts, debugInfo, method, type, out) {
        var processInfo = [];

        var duration = (new Date()).getTime() - debugInfo.startTime;
        processInfo.push(duration + "ms");

        if (!debugInfo.wasConnected) {
            processInfo.push("+conn");
        }

        if (opts.cliId) {
            processInfo.push("ID=" + opts.cliId);
        }

        var msg = "cmd-" + method + "-" + type + " (" + processInfo.join(";") + ")";
        if (out) { msg += ": \"" + out + "\""; }
        Utils.consoleDebug(msg);
    }

    function cliHandler(method, cmd, args, opts, retry) {
        var cliId     = getNextCliId(),
            deferred  = Promise.defer();

        deferredMap[cliId] = deferred;
        args = args || [];
        opts = opts || {};

        var watchProgress = args.indexOf("--progress") !== -1;

        // it is possible to set a custom working directory in options
        // otherwise the current project root is used to execute commands
        if (!opts.cwd) {
            opts.cwd = Preferences.get("currentGitRoot") || Utils.getProjectRoot();
        }

        // convert paths like c:/foo/bar to c:\foo\bar on windows
        opts.cwd = normalizePathForOs(opts.cwd);

        // log all cli communication into console when debug mode is on
        if (debugOn) {
            var startTime = (new Date()).getTime();
            Utils.consoleDebug("cmd-" + method + (watchProgress ? "-watch" : "") + ": " +
                               opts.cwd + " -> " +
                               cmd + " " + args.join(" "));
        }

        // we connect to node (promise is returned immediately if we are already connected)
        connectToNode().catch(function (err) {
            // failed to connect to node for some reason
            throw ErrorHandler.showError(new ExpectedError(err), Strings.ERROR_CONNECT_NODEJS);
        }).then(function (wasConnected) {

            var resolved      = false,
                timeoutLength = opts.timeout ? (opts.timeout * 1000) : gitTimeout;

            var domainOpts = {
                cliId: cliId,
                watchProgress: watchProgress
            };

            var debugInfo = {
                startTime: startTime,
                wasConnected: wasConnected
            };

            if (watchProgress) {
                deferred.progress("Running command: git " + args.join(" "));
            }

            // nodeConnection returns jQuery deferred
            nodeConnection.domains[domainName][method](opts.cwd, cmd, args, domainOpts)
                .fail(function (err) { // jQuery promise - .fail is fine
                    if (!resolved) {
                        err = sanitizeOutput(err);
                        if (debugOn) {
                            logDebug(domainOpts, debugInfo, method, "fail", err);
                        }
                        delete deferredMap[cliId];

                        err = ErrorHandler.toError(err);

                        // spawn ENOENT error
                        var invalidCwdErr = "spawn ENOENT";
                        if (err.stack && err.stack.indexOf(invalidCwdErr)) {
                            err.message = err.message.replace(invalidCwdErr, invalidCwdErr + " (" + opts.cwd + ")");
                            err.stack = err.stack.replace(invalidCwdErr, invalidCwdErr + " (" + opts.cwd + ")");
                        }

                        // socket was closed so we should try this once again (if not already retrying)
                        if (err.stack && err.stack.indexOf("WebSocket.self._ws.onclose") !== -1 && !retry) {
                            cliHandler(method, cmd, args, opts, true)
                                .then(function (response) {
                                    deferred.resolve(response);
                                })
                                .catch(function (err) {
                                    deferred.reject(err);
                                });
                            return;
                        }

                        deferred.reject(err);
                    }
                })
                .then(function (out) {
                    if (!resolved) {
                        out = sanitizeOutput(out);
                        if (debugOn) {
                            logDebug(domainOpts, debugInfo, method, "out", out);
                        }
                        delete deferredMap[cliId];
                        deferred.resolve(out);
                    }
                })
                .always(function () {
                    resolved = true;
                })
                .done();

            function timeoutPromise() {
                if (debugOn) {
                    logDebug(domainOpts, debugInfo, method, "timeout");
                }
                var err = new Error("cmd-" + method + "-timeout: " + cmd + " " + args.join(" "));
                if (!opts.timeoutExpected) {
                    ErrorHandler.logError(err);
                }

                // process still lives and we need to kill it
                nodeConnection.domains[domainName].kill(domainOpts.cliId)
                    .fail(function (err) {
                        ErrorHandler.logError(err);
                    });

                delete deferredMap[cliId];
                deferred.reject(ErrorHandler.toError(err));
                resolved = true;
            }

            var lastProgressTime = 0;
            function timeoutCall() {
                setTimeout(function () {
                    if (!resolved) {
                        if (typeof opts.timeoutCheck === "function") {
                            Promise.cast(opts.timeoutCheck())
                                .catch(function (err) {
                                    ErrorHandler.logError("timeoutCheck failed: " + opts.timeoutCheck.toString());
                                    ErrorHandler.logError(err);
                                })
                                .then(function (continueExecution) {
                                    if (continueExecution) {
                                        // check again later
                                        timeoutCall();
                                    } else {
                                        timeoutPromise();
                                    }
                                });
                        } else if (domainOpts.watchProgress) {
                            // we are watching the promise progress in the domain
                            // so we should check if the last message was sent in more than timeout time
                            var currentTime = (new Date()).getTime();
                            var diff = currentTime - lastProgressTime;
                            if (diff > timeoutLength) {
                                if (debugOn) {
                                    Utils.consoleDebug("cmd(" + cliId + ") - last progress message was sent " + diff + "ms ago - timeout");
                                }
                                timeoutPromise();
                            } else {
                                if (debugOn) {
                                    Utils.consoleDebug("cmd(" + cliId + ") - last progress message was sent " + diff + "ms ago - delay");
                                }
                                timeoutCall();
                            }
                        } else {
                            // we don't have any custom handler, so just kill the promise here
                            // note that command WILL keep running in the background
                            // so even when timeout occurs, operation might finish after it
                            timeoutPromise();
                        }
                    }
                }, timeoutLength);
            }

            // when opts.timeout === false then never timeout the process
            if (opts.timeout !== false) {
                // if we are watching for progress events, mark the time when last progress was made
                if (domainOpts.watchProgress) {
                    deferred.promise.progressed(function () {
                        lastProgressTime = (new Date()).getTime();
                    });
                }
                // call the method which will timeout the promise after a certain period of time
                timeoutCall();
            }

        }).catch(function (err) {
            throw ErrorHandler.showError(err, "Unexpected error in CLI handler - close all instances of Brackets and start again to reload");
        });

        return deferred.promise;
    }

    function which(cmd) {
        return cliHandler("which", cmd);
    }

    function pathExists(path) {
        return cliHandler("pathExists", path).then(function (response) {
            return typeof response === "string" ? response === "true" : response;
        });
    }

    function spawnCommand(cmd, args, opts) {
        return cliHandler("spawn", cmd, args, opts);
    }

    function executeCommand(cmd, args, opts) {
        return cliHandler("execute", cmd, args, opts);
    }

    // this is to be used together with executeCommand
    // spawnCommand does the escaping automatically
    function escapeShellArg(str) {
        if (typeof str !== "string") {
            throw new Error("escapeShellArg argument is not a string: " + typeof str);
        }
        if (str.length === 0) {
            return str;
        }
        if (brackets.platform !== "win") {
            // http://steve-parker.org/sh/escape.shtml
            str = str.replace(/["$`\\]/g, function (m) {
                return "\\" + m;
            });
            return "\"" + str + "\"";
        } else {
            // http://stackoverflow.com/questions/7760545/cmd-escape-double-quotes-in-parameter
            str = str.replace(/"/g, function () {
                return "\"\"\"";
            });
            return "\"" + str + "\"";
        }
    }

    // Public API
    exports.cliHandler      = cliHandler;
    exports.which           = which;
    exports.pathExists      = pathExists;
    exports.executeCommand  = executeCommand;
    exports.spawnCommand    = spawnCommand;
    exports.escapeShellArg  = escapeShellArg;

});
<|endoftext|>


<commit_before>angular.module('duScroll.scrollspy', ['duScroll.spyAPI'])
.directive('duScrollspy', function(spyAPI, duScrollOffset, $timeout, $rootScope) {
  'use strict';

  var Spy = function(targetElementOrId, $scope, $element, offset) {
    if(angular.isElement(targetElementOrId)) {
      this.target = targetElementOrId;
    } else if(angular.isString(targetElementOrId)) {
      this.targetId = targetElementOrId;
    }
    this.$scope = $scope;
    this.$element = $element;
    this.offset = offset;
  };

  Spy.prototype.getTargetElement = function() {
    if (!this.target && this.targetId) {
      this.target = document.getElementById(this.targetId) || document.getElementsByName(this.targetId)[0]
    }
    return this.target;
  };

  Spy.prototype.getTargetPosition = function() {
    var target = this.getTargetElement();
    if(target) {
      return target.getBoundingClientRect();
    }
  };

  Spy.prototype.flushTargetCache = function() {
    if(this.targetId) {
      this.target = undefined;
    }
  };

  return {
    link: function ($scope, $element, $attr) {
      var href = $attr.ngHref || $attr.href;
      var targetId;

      if (href && href.indexOf('#') !== -1) {
        targetId = href.replace(/.*(?=#[^\s]+$)/, '').substring(1);
      } else if($attr.duScrollspy) {
        targetId = $attr.duScrollspy;
      } else if($attr.duSmoothScroll) {
        targetId = $attr.duSmoothScroll;
      }
      if(!targetId) return;

      // Run this in the next execution loop so that the scroll context has a chance
      // to initialize
      $timeout(function() {
        var spy = new Spy(targetId, $scope, $element, -($attr.offset ? parseInt($attr.offset, 10) : duScrollOffset));
        spyAPI.addSpy(spy);

        $scope.$on('$locationChangeSuccess', spy.flushTargetCache.bind(spy));
        var deregisterOnStateChange = $rootScope.$on('$stateChangeSuccess', spy.flushTargetCache.bind(spy));
        $scope.$on('$destroy', function() {
          spyAPI.removeSpy(spy);
          deregisterOnStateChange();
        });
      }, 0, false);
    }
  };
});
<commit_msg>Fixed jslint error (missing semicolon).<commit_after>angular.module('duScroll.scrollspy', ['duScroll.spyAPI'])
.directive('duScrollspy', function(spyAPI, duScrollOffset, $timeout, $rootScope) {
  'use strict';

  var Spy = function(targetElementOrId, $scope, $element, offset) {
    if(angular.isElement(targetElementOrId)) {
      this.target = targetElementOrId;
    } else if(angular.isString(targetElementOrId)) {
      this.targetId = targetElementOrId;
    }
    this.$scope = $scope;
    this.$element = $element;
    this.offset = offset;
  };

  Spy.prototype.getTargetElement = function() {
    if (!this.target && this.targetId) {
      this.target = document.getElementById(this.targetId) || document.getElementsByName(this.targetId)[0];
    }
    return this.target;
  };

  Spy.prototype.getTargetPosition = function() {
    var target = this.getTargetElement();
    if(target) {
      return target.getBoundingClientRect();
    }
  };

  Spy.prototype.flushTargetCache = function() {
    if(this.targetId) {
      this.target = undefined;
    }
  };

  return {
    link: function ($scope, $element, $attr) {
      var href = $attr.ngHref || $attr.href;
      var targetId;

      if (href && href.indexOf('#') !== -1) {
        targetId = href.replace(/.*(?=#[^\s]+$)/, '').substring(1);
      } else if($attr.duScrollspy) {
        targetId = $attr.duScrollspy;
      } else if($attr.duSmoothScroll) {
        targetId = $attr.duSmoothScroll;
      }
      if(!targetId) return;

      // Run this in the next execution loop so that the scroll context has a chance
      // to initialize
      $timeout(function() {
        var spy = new Spy(targetId, $scope, $element, -($attr.offset ? parseInt($attr.offset, 10) : duScrollOffset));
        spyAPI.addSpy(spy);

        $scope.$on('$locationChangeSuccess', spy.flushTargetCache.bind(spy));
        var deregisterOnStateChange = $rootScope.$on('$stateChangeSuccess', spy.flushTargetCache.bind(spy));
        $scope.$on('$destroy', function() {
          spyAPI.removeSpy(spy);
          deregisterOnStateChange();
        });
      }, 0, false);
    }
  };
});
<|endoftext|>


<commit_before>
//TODO MIT license notice

function Set(elements) {
	this.bag_ = [];
	var i;

	if (arguments.length > 0) { // optional args
		for (i=0; i < elements.length; i++) {
			this.add(elements[i]);
		}
	}
}

Set.prototype.search = function(e, start) {
	//TODO document this
	var j = this.bag_.length;
	var pivot;
	var i = arguments.length == 2 ? start : 0;

	while (i < j) {
		pivot = i + Math.floor((j - i) / 2);
		if (this.bag_[pivot] == e) {
			return pivot;
		}

		if (e > this.bag_[pivot]) {
			i = pivot + 1;
		} else {
			j = pivot;
		}
	}

	return i;
}

Set.prototype.add = function(e) {
	var p = this.search(e);
	if (this.bag_[p] != e) {
		this.bag_.splice(p, 0, e); // insert e at position p
	}
}

Set.prototype.contains = function(e) {
	var p = this.search(e);
	return (this.bag_[p] == e);
}

Set.prototype.size = function() {
	return this.bag_.length;
}

Set.prototype.difference = function(otherSet) {
	var result = new Set();
	if (this.size() == 0) {return result;}

	var i;
	var j = 0;
	var a = this.bag_; var b = otherSet.bag_;
	for (i=0; i < a.length; i++) {
		if (a[i] > b[j]) {
			j = otherSet.search(a[i], j); // finds First b[j] Not Lesser than a[i]
		}

		if (j == b.length) { // end of b
			result.bag_ = result.bag_.concat(a.slice(i));
			break;
		}

		if (a[i] < b[j]) {
			result.bag_.push(a[i]);
		}
	}

	return result;
}

<commit_msg>better explicit than implicit<commit_after>
//TODO MIT license notice

function Set(elements) {
	this.bag_ = [];
	var i;

	if (arguments.length > 0) { // optional args
		for (i=0; i < elements.length; i++) {
			this.add(elements[i]);
		}
	}
}

Set.prototype.search = function(e, start) {
	//TODO document this
	var j = this.bag_.length;
	var pivot;
	var i = arguments.length == 2 ? start : 0;

	while (i < j) {
		pivot = i + Math.floor((j - i) / 2);
		if (this.bag_[pivot] == e) {
			return pivot;
		}

		if (e > this.bag_[pivot]) {
			i = pivot + 1;
		} else {
			j = pivot;
		}
	}

	return i;
}

Set.prototype.add = function(e) {
	var p = this.search(e);
	if (this.bag_[p] != e) {
		this.bag_.splice(p, 0, e); // insert e at position p
	}
}

Set.prototype.contains = function(e) {
	var p = this.search(e);
	return (this.bag_[p] == e);
}

Set.prototype.size = function() {
	return this.bag_.length;
}

Set.prototype.difference = function(otherSet) {
	var result = new Set();

	if (this.size() == 0) {return result;}
	if (otherSet.size() == 0) {
		result.bag_ = this.bag_.slice(0);
		return result;
	}

	var i;
	var j = 0;
	var a = this.bag_; var b = otherSet.bag_;
	for (i=0; i < a.length; i++) {
		if (a[i] > b[j]) {
			j = otherSet.search(a[i], j); // finds First b[j] Not Lesser than a[i]
		}

		if (j == b.length) { // end of b
			result.bag_ = result.bag_.concat(a.slice(i));
			break;
		}

		if (a[i] < b[j]) {
			result.bag_.push(a[i]);
		}
	}

	return result;
}

<|endoftext|>


<commit_before>function readFile(fileName) {
fs = require('fs')
jsql = require('json-sql')
fs.readFile('cometData.json', 'utf8', function (err,data) {
  if (err) {
    return err;
  }
  return data;
});
}
<commit_msg>bug fix<commit_after>function readFile(fileName) {
fs = require('fs')

fs.readFile(fileName, 'utf8', function (err,data) {
  if (err) {
    return err;
  }
  return data;
});
}
<|endoftext|>


<commit_before>(function(jQuery) {
"use strict";

if (Echo.AppServer.Dashboard.isDefined("Echo.Apps.TopicRadar.Dashboard.List")) return;

var list = Echo.AppServer.Dashboard.manifest("Echo.Apps.TopicRadar.Dashboard.List");

list.events = {
	"Echo.AppServer.Controls.Bundler.Item.onExpand": function() {
		return {"stop": ["bubble", "propagation"]};
	},
	"Echo.Apps.TopicRadar.Dashboard.Item.onRemove": function(_, data) {
		this.removeItem(data.id);
	}
};

list.labels = {
	"addnewItem": "Add new item",
	"defaultItemTitle": "Item {index}"
};

list.vars = {
	"items": [],
	"itemsCounter": 0
};

list.config = {
	"item": {
		"component": ""
	}
};

list.templates.main =
	'
' +
		'

' +
		'
{label:addNewItem}
' +
	'
';

list.init = function() {
	this.set("items", this._prepareItems(this.get("data.value")));
	this.parent();
};

list.renderers.list = function(element) {
	$.map(this.get("items"), function(item) {
		element.append(item.config.get("target"));
	});
	return element;
};

list.renderers.newItem = function(element) {
	var self = this;
	return element
		.addClass("echo-clickable")
		.on("click", function() {
			self.addItem();
		});
};

list.methods.addItem = function(data) {
	var self = this;
	var items = this.get("items");
	this._initItem(
		$.extend(true, {}, data),
		function() {
			items.push(this);
			self.events.publish({
				"topic": "onItemAdd",
				"inherited": true
			});
			self.view.render({"name": "list"});
		}
	);
};

list.methods.removeItem = function(id) {
	var items = this.get("items");
	$.each(items, function(index, item) {
		if (item.get("data.id") === id) {
			var removedItem = items.splice(index, 1)[0];
			removedItem.config.get("target").detach();
			removedItem.destroy();
			return false;
		}
	});
	this.view.render({"name": "list"});
};

list.methods.isValueEquals = function() {
	return false;
};

list.methods.value = function() {
	return $.map(this.get("items"), function(item) {
		return item.value();
	});
};

list.methods._prepareItems = function(items) {
	var self = this;
	var Component = Echo.Utils.getComponent(this.config.get("item.component"));

	return Component
		? $.map(items || [], function(item) {
				return self._initItem(item);
			})
		: [];
};

list.methods._initItem = function(data, callback) {
	var Component = Echo.Utils.getComponent(this.config.get("item.component"));
	return Component
		&& new Component({
			"target": $("
"),
			"context": this.config.get("context"),
			"cdnBaseURL": this.config.get("cdnBaseURL"),
			"dashboard": this.config.get("dashboard"),
			"data": $.extend(true, data, {
				"title": data.title || this.labels.get("defaultItemTitle", {"index": ++this.itemsCounter})
			}),
			"ready": function() {
				callback && callback.call(this);
			}
		});
};

list.css =
	'.{class:newItem} { background: left center no-repeat url({config:cdnBaseURL.apps.appserver}/images/plus.png); }' +
	'.{class:newItem} { margin-left: 26px; margin-top: 10px; margin-bottom: 10px; padding-left: 23px; font: 12px Arial; font-weight: bold; color: #787878; }';

Echo.AppServer.Dashboard.create(list);

})(Echo.jQuery);
<commit_msg>fix issue with list items counter<commit_after>(function(jQuery) {
"use strict";

if (Echo.AppServer.Dashboard.isDefined("Echo.Apps.TopicRadar.Dashboard.List")) return;

var list = Echo.AppServer.Dashboard.manifest("Echo.Apps.TopicRadar.Dashboard.List");

list.events = {
	"Echo.AppServer.Controls.Bundler.Item.onExpand": function() {
		return {"stop": ["bubble", "propagation"]};
	},
	"Echo.Apps.TopicRadar.Dashboard.Item.onRemove": function(_, data) {
		this.removeItem(data.id);
	}
};

list.labels = {
	"addnewItem": "Add new item",
	"defaultItemTitle": "Item {index}"
};

list.vars = {
	"items": [],
	"itemsCounter": 0
};

list.config = {
	"item": {
		"component": ""
	}
};

list.templates.main =
	'
' +
		'

' +
		'
{label:addNewItem}
' +
	'
';

list.init = function() {
	this.set("items", this._prepareItems(this.get("data.value")));
	this.parent();
};

list.renderers.list = function(element) {
	$.map(this.get("items"), function(item) {
		element.append(item.config.get("target"));
	});
	return element;
};

list.renderers.newItem = function(element) {
	var self = this;
	return element
		.addClass("echo-clickable")
		.on("click", function() {
			self.addItem();
		});
};

list.methods.addItem = function(data) {
	var self = this;
	var items = this.get("items");
	this._initItem(
		$.extend(true, {}, data),
		function() {
			items.push(this);
			self.events.publish({
				"topic": "onItemAdd",
				"inherited": true
			});
			self.view.render({"name": "list"});
		}
	);
};

list.methods.removeItem = function(id) {
	var items = this.get("items");
	$.each(items, function(index, item) {
		if (item.get("data.id") === id) {
			var removedItem = items.splice(index, 1)[0];
			removedItem.config.get("target").detach();
			removedItem.destroy();
			return false;
		}
	});
	this.view.render({"name": "list"});
};

list.methods.isValueEquals = function() {
	return false;
};

list.methods.value = function() {
	return $.map(this.get("items"), function(item) {
		return item.value();
	});
};

list.methods._prepareItems = function(items) {
	var self = this;
	var Component = Echo.Utils.getComponent(this.config.get("item.component"));

	return Component
		? $.map(items || [], function(item) {
				return self._initItem(item);
			})
		: [];
};

list.methods._initItem = function(data, callback) {
	var Component = Echo.Utils.getComponent(this.config.get("item.component"));
	this.itemsCounter++;
	return Component
		&& new Component({
			"target": $("
"),
			"context": this.config.get("context"),
			"cdnBaseURL": this.config.get("cdnBaseURL"),
			"dashboard": this.config.get("dashboard"),
			"data": $.extend(true, data, {
				"title": data.title || this.labels.get("defaultItemTitle", {"index": this.itemsCounter})
			}),
			"ready": function() {
				callback && callback.call(this);
			}
		});
};

list.css =
	'.{class:newItem} { background: left center no-repeat url({config:cdnBaseURL.apps.appserver}/images/plus.png); }' +
	'.{class:newItem} { margin-left: 26px; margin-top: 10px; margin-bottom: 10px; padding-left: 23px; font: 12px Arial; font-weight: bold; color: #787878; }';

Echo.AppServer.Dashboard.create(list);

})(Echo.jQuery);
<|endoftext|>


<commit_before>/**
 * Copyright 2018-present Facebook.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 * @format
 */

import type {ChildProcess} from 'child_process';
import type {Store} from '../reducers/index.js';
import type Logger from '../fb-stubs/Logger.js';

import child_process from 'child_process';
import IOSDevice from '../devices/IOSDevice';

type iOSSimulatorDevice = {|
  state: 'Booted' | 'Shutdown' | 'Shutting Down',
  availability: string,
  name: string,
  udid: string,
|};

type IOSDeviceMap = {[id: string]: Array<iOSSimulatorDevice>};

// start port forwarding server for real device connections
const portForwarder: ChildProcess = child_process.exec(
  'PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp -portForward=8088 -multiplexChannelPort=8078',
);
window.addEventListener('beforeunload', () => {
  portForwarder.kill();
});

function querySimulatorDevices(): Promise<IOSDeviceMap> {
  return new Promise((resolve, reject) => {
    child_process.execFile(
      'xcrun',
      ['simctl', 'list', 'devices', '--json'],
      {encoding: 'utf8'},
      (err, stdout) => {
        if (err) {
          reject(err);
        }

        try {
          const {devices} = JSON.parse(stdout.toString());
          resolve(devices);
        } catch (err) {
          reject(err);
        }
      },
    );
  });
}

export default (store: Store, logger: Logger) => {
  // monitoring iOS devices only available on MacOS.
  if (process.platform !== 'darwin') {
    return;
  }
  const simulatorUpdateInterval = setInterval(() => {
    const {connections} = store.getState();
    querySimulatorDevices()
      .then((simulatorDevices: IOSDeviceMap) => {
        const simulators: Array<iOSSimulatorDevice> = Object.values(
          simulatorDevices,
          // $FlowFixMe
        ).reduce((acc, cv) => acc.concat(cv), []);

        const currentDeviceIDs: Set<string> = new Set(
          connections.devices
            .filter(device => device instanceof IOSDevice)
            .map(device => device.serial),
        );

        const deviceIDsToRemove = new Set();
        simulators.forEach((simulator: iOSSimulatorDevice) => {
          const isRunning =
            simulator.state === 'Booted' &&
            simulator.availability === '(available)';

          if (isRunning && !currentDeviceIDs.has(simulator.udid)) {
            // create device
            store.dispatch({
              type: 'REGISTER_DEVICE',
              payload: new IOSDevice(
                simulator.udid,
                'emulator',
                simulator.name,
              ),
            });
          } else if (!isRunning && currentDeviceIDs.has(simulator.udid)) {
            deviceIDsToRemove.add(simulator.udid);
            // delete device
          }
        });

        if (deviceIDsToRemove.size > 0) {
          store.dispatch({
            type: 'UNREGISTER_DEVICES',
            payload: deviceIDsToRemove,
          });
        }
      })
      .catch(err => {
        console.error(err);
        clearInterval(simulatorUpdateInterval);
      });
  }, 3000);
};
<commit_msg>faster iOS device connection<commit_after>/**
 * Copyright 2018-present Facebook.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 * @format
 */

import type {ChildProcess} from 'child_process';
import type {Store} from '../reducers/index.js';
import type Logger from '../fb-stubs/Logger.js';

import {promisify} from 'util';
import child_process from 'child_process';
const exec = promisify(child_process.exec);
const execFile = promisify(child_process.execFile);
import IOSDevice from '../devices/IOSDevice';

type iOSSimulatorDevice = {|
  state: 'Booted' | 'Shutdown' | 'Shutting Down',
  availability: string,
  name: string,
  udid: string,
|};

type IOSDeviceMap = {[id: string]: Array<iOSSimulatorDevice>};

// start port forwarding server for real device connections
const portForwarder: ChildProcess = exec(
  'PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp -portForward=8088 -multiplexChannelPort=8078',
);
window.addEventListener('beforeunload', () => {
  portForwarder.kill();
});

function querySimulatorDevices(store: Store): Promise<IOSDeviceMap> {
  const {connections} = store.getState();

  return execFile('xcrun', ['simctl', 'list', 'devices', '--json'], {
    encoding: 'utf8',
  })
    .then(({stdout}) => JSON.parse(stdout).devices)
    .then((simulatorDevices: IOSDeviceMap) => {
      const simulators: Array<iOSSimulatorDevice> = Object.values(
        simulatorDevices,
        // $FlowFixMe
      ).reduce((acc, cv) => acc.concat(cv), []);

      const currentDeviceIDs: Set<string> = new Set(
        connections.devices
          .filter(device => device instanceof IOSDevice)
          .map(device => device.serial),
      );

      const deviceIDsToRemove = new Set();
      simulators.forEach((simulator: iOSSimulatorDevice) => {
        const isRunning =
          simulator.state === 'Booted' &&
          simulator.availability === '(available)';

        if (isRunning && !currentDeviceIDs.has(simulator.udid)) {
          // create device
          store.dispatch({
            type: 'REGISTER_DEVICE',
            payload: new IOSDevice(simulator.udid, 'emulator', simulator.name),
          });
        } else if (!isRunning && currentDeviceIDs.has(simulator.udid)) {
          deviceIDsToRemove.add(simulator.udid);
          // delete device
        }
      });

      if (deviceIDsToRemove.size > 0) {
        store.dispatch({
          type: 'UNREGISTER_DEVICES',
          payload: deviceIDsToRemove,
        });
      }
    });
}

export default (store: Store, logger: Logger) => {
  // monitoring iOS devices only available on MacOS.
  if (process.platform !== 'darwin') {
    return;
  }
  querySimulatorDevices(store)
    .then(() => {
      const simulatorUpdateInterval = setInterval(() => {
        querySimulatorDevices(store).catch(err => {
          console.error(err);
          clearInterval(simulatorUpdateInterval);
        });
      }, 3000);
    })
    .catch(console.error);
};
<|endoftext|>


<commit_before>PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight)
{
	var target = posOptions.target,
		tooltip = api.elements.tooltip,
		my = posOptions.my,
		at = posOptions.at,
		adjust = posOptions.adjust,
		method = adjust.method.split(' '),
		methodX = method[0],
		methodY = method[1] || method[0],
		viewport = posOptions.viewport,
		container = posOptions.container,
		cache = api.cache,
		adjusted = { left: 0, top: 0 },
		fixed, newMy, containerOffset, containerStatic,
		viewportWidth, viewportHeight, viewportScroll, viewportOffset, viewportDeflate;

	// If viewport is not a jQuery element, or it's the window/document, or no adjustment method is used... return
	if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') {
		return adjusted;
	}

	// Cach container details
	containerOffset = container.offset() || adjusted;
	containerStatic = container.css('position') === 'static';

	// Cache our viewport details
	fixed = tooltip.css('position') === 'fixed';
	viewportWidth = viewport[0] === window ? viewport.width() : viewport.outerWidth(FALSE);
	viewportHeight = viewport[0] === window ? viewport.height() : viewport.outerHeight(FALSE);
	viewportScroll = { left: fixed ? 0 : viewport.scrollLeft(), top: fixed ? 0 : viewport.scrollTop() };
	viewportOffset = viewport.offset() || adjusted;

	// Deflate (or inflate) the viewport edges
	viewportDeflate = posOptions.viewportDeflate;
	viewportOffset.top += viewportDeflate.top;
	viewportOffset.left += viewportDeflate.left;
	viewportHeight -= (viewportDeflate.top + viewportDeflate.bottom);
	viewportWidth -= (viewportDeflate.left + viewportDeflate.right);

	// Generic calculation method
	function calculate(side, otherSide, type, adjust, side1, side2, lengthName, targetLength, elemLength) {
		var initialPos = position[side1],
			mySide = my[side],
			atSide = at[side],
			isShift = type === SHIFT,
			myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2,
			atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2,
			sideOffset = viewportScroll[side1] + viewportOffset[side1] - (containerStatic ? 0 : containerOffset[side1]),
			overflow1 = sideOffset - initialPos,
			overflow2 = initialPos + elemLength - (lengthName === WIDTH ? viewportWidth : viewportHeight) - sideOffset,
			offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0);

		// shift
		if(isShift) {
			offset = (mySide === side1 ? 1 : -1) * myLength;

			// Adjust position but keep it within viewport dimensions
			position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0;
			position[side1] = Math.max(
				-containerOffset[side1] + viewportOffset[side1],
				initialPos - offset,
				Math.min(
					Math.max(
						-containerOffset[side1] + viewportOffset[side1] + (lengthName === WIDTH ? viewportWidth : viewportHeight),
						initialPos + offset
					),
					position[side1],

					// Make sure we don't adjust complete off the element when using 'center'
					mySide === 'center' ? initialPos - myLength : 1E9
				)
			);

		}

		// flip/flipinvert
		else {
			// Update adjustment amount depending on if using flipinvert or flip
			adjust *= (type === FLIPINVERT ? 2 : 0);

			// Check for overflow on the left/top
			if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) {
				position[side1] -= offset + adjust;
				newMy.invert(side, side1);
			}

			// Check for overflow on the bottom/right
			else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0)  ) {
				position[side1] -= (mySide === CENTER ? -offset : offset) + adjust;
				newMy.invert(side, side2);
			}

			// Make sure we haven't made things worse with the adjustment and reset if so
			if(position[side1] < viewportScroll && -position[side1] > overflow2) {
				position[side1] = initialPos; newMy = my.clone();
			}
		}

		return position[side1] - initialPos;
	}

	// Set newMy if using flip or flipinvert methods
	if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); }

	// Adjust position based onviewport and adjustment options
	adjusted = {
		left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0,
		top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0,
		my: newMy
	};

	return adjusted;
};
<commit_msg>Pick up the jquery3 change from the frontend<commit_after>PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight)
{
	var target = posOptions.target,
		tooltip = api.elements.tooltip,
		my = posOptions.my,
		at = posOptions.at,
		adjust = posOptions.adjust,
		method = adjust.method.split(' '),
		methodX = method[0],
		methodY = method[1] || method[0],
		viewport = posOptions.viewport,
		container = posOptions.container,
		cache = api.cache,
		adjusted = { left: 0, top: 0 },
		fixed, newMy, containerOffset, containerStatic,
		viewportWidth, viewportHeight, viewportScroll, viewportOffset, viewportDeflate;

	// If viewport is not a jQuery element, or it's the window/document, or no adjustment method is used... return
	if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') {
		return adjusted;
	}

	// Cach container details
	containerOffset = container.offset() || adjusted;
	containerStatic = container.css('position') === 'static';

	// Cache our viewport details
	fixed = tooltip.css('position') === 'fixed';
	viewportWidth = viewport[0] === window ? viewport.width() : viewport.outerWidth(FALSE);
	viewportHeight = viewport[0] === window ? viewport.height() : viewport.outerHeight(FALSE);
	viewportScroll = { left: fixed ? 0 : viewport.scrollLeft(), top: fixed ? 0 : viewport.scrollTop() };
	viewportOffset = (viewport[0] !== window && viewport.offset()) || adjusted;

	// Deflate (or inflate) the viewport edges
	viewportDeflate = posOptions.viewportDeflate;
	viewportOffset.top += viewportDeflate.top;
	viewportOffset.left += viewportDeflate.left;
	viewportHeight -= (viewportDeflate.top + viewportDeflate.bottom);
	viewportWidth -= (viewportDeflate.left + viewportDeflate.right);

	// Generic calculation method
	function calculate(side, otherSide, type, adjust, side1, side2, lengthName, targetLength, elemLength) {
		var initialPos = position[side1],
			mySide = my[side],
			atSide = at[side],
			isShift = type === SHIFT,
			myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2,
			atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2,
			sideOffset = viewportScroll[side1] + viewportOffset[side1] - (containerStatic ? 0 : containerOffset[side1]),
			overflow1 = sideOffset - initialPos,
			overflow2 = initialPos + elemLength - (lengthName === WIDTH ? viewportWidth : viewportHeight) - sideOffset,
			offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0);

		// shift
		if(isShift) {
			offset = (mySide === side1 ? 1 : -1) * myLength;

			// Adjust position but keep it within viewport dimensions
			position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0;
			position[side1] = Math.max(
				-containerOffset[side1] + viewportOffset[side1],
				initialPos - offset,
				Math.min(
					Math.max(
						-containerOffset[side1] + viewportOffset[side1] + (lengthName === WIDTH ? viewportWidth : viewportHeight),
						initialPos + offset
					),
					position[side1],

					// Make sure we don't adjust complete off the element when using 'center'
					mySide === 'center' ? initialPos - myLength : 1E9
				)
			);

		}

		// flip/flipinvert
		else {
			// Update adjustment amount depending on if using flipinvert or flip
			adjust *= (type === FLIPINVERT ? 2 : 0);

			// Check for overflow on the left/top
			if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) {
				position[side1] -= offset + adjust;
				newMy.invert(side, side1);
			}

			// Check for overflow on the bottom/right
			else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0)  ) {
				position[side1] -= (mySide === CENTER ? -offset : offset) + adjust;
				newMy.invert(side, side2);
			}

			// Make sure we haven't made things worse with the adjustment and reset if so
			if(position[side1] < viewportScroll && -position[side1] > overflow2) {
				position[side1] = initialPos; newMy = my.clone();
			}
		}

		return position[side1] - initialPos;
	}

	// Set newMy if using flip or flipinvert methods
	if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); }

	// Adjust position based onviewport and adjustment options
	adjusted = {
		left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0,
		top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0,
		my: newMy
	};

	return adjusted;
};
<|endoftext|>


<commit_before>import React from 'react';

import Icon from 'common/Icon';
import { formatThousands } from 'common/format';
import { formatPercentage } from 'common/format';

import Analyzer from 'Parser/Core/Analyzer';

import SmallStatisticBox, { STATISTIC_ORDER } from 'Main/SmallStatisticBox';

const debug = false;

class DistanceMoved extends Analyzer {
  lastPositionUpdate = null;
  totalDistanceMoved = 0;
  timeSpentMoving = 0;

  // Events
  on_cast(event) {
    if (this.owner.byPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  on_damage(event) {
    if (this.owner.toPlayer(event)) {
      // Damage coordinates are for the target, so they are only accurate when done TO player
      this.updatePlayerPosition(event);
    }
  }

  on_energize(event) {
    if (this.owner.toPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  on_heal(event) {
    if (this.owner.toPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  on_absorbed(event) {
    if (this.owner.toPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  // Data parsing
  calculateDistance(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) / 100;
  }

  updateTotalDistance(event) {
    if (!this.lastPositionUpdate) {
      return;
    }
    const distanceMoved = this.calculateDistance(this.lastPositionUpdate.x, this.lastPositionUpdate.y, event.x, event.y);
    if (distanceMoved !== 0) {
      this.timeSpentMoving += event.timestamp - this.lastPositionUpdate.timestamp;
      this.totalDistanceMoved += distanceMoved;
    }
  }

  updatePlayerPosition(event) {
    if (!event.x || !event.y) {
      return;
    }
    this.updateTotalDistance(event);
    this.lastPositionUpdate = event;
  }

  statistic() {
    const dist_value = `≈${formatThousands(this.totalDistanceMoved)} yards`;
    const dist_label = "Distance moved";
    const dist_tooltip = `≈${formatThousands(this.totalDistanceMoved / (this.owner.fightDuration / 1000) * 60)} yards per minute. Consider this when analyzing the fight, as some fights require more movement than others. Unnecessary movement can result in a DPS/HPS loss.`;
    const dist_icon = <Icon icon="spell_fire_burningspeed" />;

    const timeMoving_value = `≈${formatPercentage(this.timeSpentMoving / (this.owner.fightDuration))}%`;
    const timeMoving_label = "Time spent moving";
    const timeMoving_tooltip = `In ≈${formatThousands(this.timeSpentMoving / 1000)} seconds of movement you moved ≈${formatThousands(this.totalDistanceMoved)} yards. This statistic is not entirely accurate and may be overstated for fights with lots of problems.`;
    const timeMoving_icon = <Icon icon="inv_misc_pocketwatch_02" />;

    debug && console.log(`Time spent moving: ${this.timeSpentMoving / 1000} s, Total distance moved: ${this.totalDistanceMoved} yds`);

    return (

              {dist_icon} {dist_label}

              {dist_tooltip ? <dfn data-tip={dist_tooltip}>{dist_value}</dfn> : dist_value}

              {timeMoving_icon} {timeMoving_label}

              {timeMoving_tooltip ? <dfn data-tip={timeMoving_tooltip}>{timeMoving_value}</dfn> : timeMoving_value}

    );
  }
  statisticOrder = STATISTIC_ORDER.UNIMPORTANT();
}

export default DistanceMoved;
<commit_msg>remove nonused import<commit_after>import React from 'react';

import Icon from 'common/Icon';
import { formatThousands } from 'common/format';
import { formatPercentage } from 'common/format';

import Analyzer from 'Parser/Core/Analyzer';

import { STATISTIC_ORDER } from 'Main/SmallStatisticBox';

const debug = false;

class DistanceMoved extends Analyzer {
  lastPositionUpdate = null;
  totalDistanceMoved = 0;
  timeSpentMoving = 0;

  // Events
  on_cast(event) {
    if (this.owner.byPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  on_damage(event) {
    if (this.owner.toPlayer(event)) {
      // Damage coordinates are for the target, so they are only accurate when done TO player
      this.updatePlayerPosition(event);
    }
  }

  on_energize(event) {
    if (this.owner.toPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  on_heal(event) {
    if (this.owner.toPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  on_absorbed(event) {
    if (this.owner.toPlayer(event)) {
      this.updatePlayerPosition(event);
    }
  }

  // Data parsing
  calculateDistance(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) / 100;
  }

  updateTotalDistance(event) {
    if (!this.lastPositionUpdate) {
      return;
    }
    const distanceMoved = this.calculateDistance(this.lastPositionUpdate.x, this.lastPositionUpdate.y, event.x, event.y);
    if (distanceMoved !== 0) {
      this.timeSpentMoving += event.timestamp - this.lastPositionUpdate.timestamp;
      this.totalDistanceMoved += distanceMoved;
    }
  }

  updatePlayerPosition(event) {
    if (!event.x || !event.y) {
      return;
    }
    this.updateTotalDistance(event);
    this.lastPositionUpdate = event;
  }

  statistic() {
    const dist_value = `≈${formatThousands(this.totalDistanceMoved)} yards`;
    const dist_label = "Distance moved";
    const dist_tooltip = `≈${formatThousands(this.totalDistanceMoved / (this.owner.fightDuration / 1000) * 60)} yards per minute. Consider this when analyzing the fight, as some fights require more movement than others. Unnecessary movement can result in a DPS/HPS loss.`;
    const dist_icon = <Icon icon="spell_fire_burningspeed" />;

    const timeMoving_value = `≈${formatPercentage(this.timeSpentMoving / (this.owner.fightDuration))}%`;
    const timeMoving_label = "Time spent moving";
    const timeMoving_tooltip = `In ≈${formatThousands(this.timeSpentMoving / 1000)} seconds of movement you moved ≈${formatThousands(this.totalDistanceMoved)} yards. This statistic is not entirely accurate and may be overstated for fights with lots of problems.`;
    const timeMoving_icon = <Icon icon="inv_misc_pocketwatch_02" />;

    debug && console.log(`Time spent moving: ${this.timeSpentMoving / 1000} s, Total distance moved: ${this.totalDistanceMoved} yds`);

    return (

              {dist_icon} {dist_label}

              {dist_tooltip ? <dfn data-tip={dist_tooltip}>{dist_value}</dfn> : dist_value}

              {timeMoving_icon} {timeMoving_label}

              {timeMoving_tooltip ? <dfn data-tip={timeMoving_tooltip}>{timeMoving_value}</dfn> : timeMoving_value}

    );
  }
  statisticOrder = STATISTIC_ORDER.UNIMPORTANT();
}

export default DistanceMoved;
<|endoftext|>


<commit_before>var VIE;
VIE = function(config) {
    this.config = (config) ? config : {};
    this.services = {};
    this.entities = new this.Collection();

    this.Entity.prototype.entities = this.entities;
    this.entities.vie = this;
    this.Entity.prototype.entityCollection = this.Collection;
    this.Entity.prototype.vie = this;

    this.defaultProxyUrl = (this.config.defaultProxyUrl) ? this.config.defaultProxyUrl : "../utils/proxy/proxy.php";

    this.Namespaces.prototype.vie = this;
    this.namespaces = new this.Namespaces(
        (this.config.defaultNamespace) ? this.config.defaultNamespace : "http://ontology.vie.js/"
    );

    this.Type.prototype.vie = this;
    this.Types.prototype.vie = this;
    this.Attribute.prototype.vie = this;
    this.Attributes.prototype.vie = this;
    this.types = new this.Types();
    this.types.add("Thing");

    if (this.config.classic !== false) {
        // Load Classic API as well
        this.RDFa = new this.ClassicRDFa(this);
        this.RDFaEntities = new this.ClassicRDFaEntities(this);
        this.EntityManager = new this.ClassicEntityManager(this);

        this.cleanup = function() {
            this.entities.reset();
        };
    }
};

VIE.prototype.use = function(service, name) {
  if (!name) {
    name = service.name;
  }
  service.vie = this;
  service.name = name;
  if (service.init) {
      service.init();
  }
  this.services[name] = service;
};

VIE.prototype.service = function(name) {
  if (!this.services[name]) {
    throw "Undefined service " + name;
  }
  return this.services[name];
};

VIE.prototype.getServicesArray = function() {
  var res = [];
  _(this.services).each(function(service, i){res.push(service);});
  return res;
};

// Declaring the ..able classes
// Loadable
VIE.prototype.load = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Loadable(options);
};

// Savable
VIE.prototype.save = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Savable(options);
};

// Removable
VIE.prototype.remove = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Removable(options);
};

// Analyzable
VIE.prototype.analyze = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Analyzable(options);
};

// Findable
VIE.prototype.find = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Findable(options);
};

if(typeof(exports) !== 'undefined' && exports !== null) {
    exports.VIE = VIE;
}
<commit_msg>Handle Node.js autoloading<commit_after>var VIE;
VIE = function(config) {
    this.config = (config) ? config : {};
    this.services = {};
    this.entities = new this.Collection();

    this.Entity.prototype.entities = this.entities;
    this.entities.vie = this;
    this.Entity.prototype.entityCollection = this.Collection;
    this.Entity.prototype.vie = this;

    this.defaultProxyUrl = (this.config.defaultProxyUrl) ? this.config.defaultProxyUrl : "../utils/proxy/proxy.php";

    this.Namespaces.prototype.vie = this;
    this.namespaces = new this.Namespaces(
        (this.config.defaultNamespace) ? this.config.defaultNamespace : "http://ontology.vie.js/"
    );

    this.Type.prototype.vie = this;
    this.Types.prototype.vie = this;
    this.Attribute.prototype.vie = this;
    this.Attributes.prototype.vie = this;
    this.types = new this.Types();
    this.types.add("Thing");

    if (this.config.classic !== false) {
        // Load Classic API as well
        this.RDFa = new this.ClassicRDFa(this);
        this.RDFaEntities = new this.ClassicRDFaEntities(this);
        this.EntityManager = new this.ClassicEntityManager(this);

        this.cleanup = function() {
            this.entities.reset();
        };
    }
};

VIE.prototype.use = function(service, name) {
  if (!name) {
    name = service.name;
  }
  service.vie = this;
  service.name = name;
  if (service.init) {
      service.init();
  }
  this.services[name] = service;
};

VIE.prototype.service = function(name) {
  if (!this.services[name]) {
    throw "Undefined service " + name;
  }
  return this.services[name];
};

VIE.prototype.getServicesArray = function() {
  var res = [];
  _(this.services).each(function(service, i){res.push(service);});
  return res;
};

// Declaring the ..able classes
// Loadable
VIE.prototype.load = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Loadable(options);
};

// Savable
VIE.prototype.save = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Savable(options);
};

// Removable
VIE.prototype.remove = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Removable(options);
};

// Analyzable
VIE.prototype.analyze = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Analyzable(options);
};

// Findable
VIE.prototype.find = function(options) {
  if (!options) { options = {}; }
  options.vie = this;
  return new this.Findable(options);
};

if(typeof exports === 'object') {
    // Running under Node.js or other CommonJS environment
    exports.VIE = VIE;
    var jQuery = require('jquery');
    var Backbone = require('backbone');
    var _ = require('underscore')._;
}
<|endoftext|>


<commit_before>var thumbImgUrl = "";
var bgImgUrl = "";
var categoryId = 1;
var insertOrUpdate = 0;
var categoryVue;
/**
 * 初始化下拉列表框
 */
$.getJSON("../category/getCategoryByPage", {
	offset: 0,
	limit: 1000
}, function(data) {
	categoryVue = new Vue({
		el: '#dropdown',
		data: {
			selected: '',
			menus: data.object.list
		},
		mounted: function() {
			$('#dropdown select').material_select();
			$('#categorySelect').change(function() {
				categoryVue.selected = $('#categorySelect').val();
			});

		},
		watch: {
			selected: function(value) {
				searchOrSelect = 0;
				categoryId = value;
			}
		}
	})
});

var thumbUploader = new plupload.Uploader({
	runtimes: 'html5,flash,silverlight,html4',
	browse_button: 'uploadThumb',
	//multi_selection: false,
	//container: document.getElementById('container'),
	flash_swf_url: '../resources/js/plupload-2.3.1/Moxie.swf',
	silverlight_xap_url: '../resources/js/plupload-2.3.1/Moxie.xap',
	url: 'http://oss.aliyuncs.com',

	filters: {
		mime_types: [ //只允许上传图片和zip,rar文件
			{
				title: "Image files",
				extensions: "jpg,jpeg,png",
				mimeTypes: 'image/jpg,image/jpeg,image/png'
			}
		],
		max_file_size: '1mb', //最大只能上传10mb的文件
		prevent_duplicates: true
		//不允许选取重复文件
	},

	init: {
		PostInit: function() {
			$("#console").html('');
			serverUrl = '../uploadKey/3';
		},

		FilesAdded: function(up, files) {
			$("#ossThumbProgress").show();
			plupload.each(files,
				function(file) {
					$("#thumbFileDescribe").append(file.name + ' (' + plupload.formatSize(file.size) + ') ');
				});
			$("#ossBgfile .determinate").show();
			set_upload_param(thumbUploader, '', false);
		},

		BeforeUpload: function(up, file) {

			set_upload_param(up, file.name, true);
		},

		UploadProgress: function(up, file) {
			$("#thumbFileCompletePersent").html(file.percent + '% ,');
			$("#ossThumbfile .determinate").width(file.percent + '%');
		},

		FileUploaded: function(up, file, info) {
			if(info.status == 200) {
				$("#thumbFileDescribe").innerHTML = '，上传成功！';
				thumbImgUrl = host + "/" + get_uploaded_object_name(file.name) + "?x-oss-process=style/thumb-300";
				$("#uploadThumb").attr('src', thumbImgUrl);

			} else {
				$("#thumbFileDescribe").innerHTML = info.response;
			}
		},

		Error: function(up, err) {
			if(err.code == -600) {
				$("#thumbConsole").html('选择的文件太大了，不能超过1M!');

			} else if(err.code == -601) {
				$("#thumbConsole").html('选择的文件后缀不对!');

			} else if(err.code == -602) {
				$("#thumbConsole").html("这个文件已经上传过一遍了");
			} else {
				$("#thumbConsole").html("上传出错！");
			}
		}
	}
});

thumbUploader.init();

var bgUploader = new plupload.Uploader({
	runtimes: 'html5,flash,silverlight,html4',
	browse_button: 'uploadBg',
	//multi_selection: false,
	//container: document.getElementById('container'),
	flash_swf_url: '../resources/js/plupload-2.3.1/Moxie.swf',
	silverlight_xap_url: '../resources/js/plupload-2.3.1/Moxie.xap',
	url: 'http://oss.aliyuncs.com',

	filters: {
		mime_types: [ //只允许上传图片和zip,rar文件
			{
				title: "Image files",
				extensions: "jpg,jpeg,png",
				mimeTypes: 'image/jpg,image/jpeg,image/png'
			}
		],
		max_file_size: '10mb', //最大只能上传10mb的文件
		prevent_duplicates: true
		//不允许选取重复文件
	},

	init: {
		PostInit: function() {
			$("#console").html('');
			serverUrl = '../uploadKey/3';
		},

		FilesAdded: function(up, files) {
			$("#ossBgfile .progress").show();
			plupload.each(files,
				function(file) {
					$("#bgFileDescribe").append(file.name + ' (' + plupload.formatSize(file.size) + ') ');
				});
			$("#ossBgProgress").show();
			set_upload_param(bgUploader, '', false);
		},

		BeforeUpload: function(up, file) {

			set_upload_param(up, file.name, true);
		},

		UploadProgress: function(up, file) {
			$("#bgFileCompletePersent").html(file.percent + '% ,');
			$("#ossBgfile .determinate").width(file.percent + '%');
		},

		FileUploaded: function(up, file, info) {
			if(info.status == 200) {
				$("#bgFileDescribe").innerHTML = '，上传成功！';
				bgImgUrl = host + "/" + get_uploaded_object_name(file.name) + "?x-oss-process=style/thumb-300";
				$("#uploadBg").attr('src', bgImgUrl);

			} else {
				$("#bgFileDescribe").innerHTML = info.response;
			}
		},

		Error: function(up, err) {
			if(err.code == -600) {
				$("#bgConsole").html('选择的文件太大了，不能超过10M!');

			} else if(err.code == -601) {
				$("#bgConsole").html('选择的文件后缀不对!');

			} else if(err.code == -602) {
				$("#bgConsole").html("这个文件已经上传过一遍了");
			} else {
				$("#bgConsole").html("上传出错！");
			}
		}
	}
});

bgUploader.init();

function loadingArticleById(id,ue) {

	$.ajax({
		type: "POST",
		url: "../article/getArticleDetailById/" + id,
		contentType: 'application/json',
		dataType: "json",
		beforeSend: function() {
			$("#circleProgress").show();
		},
		success: function(data) {
			$("#title").val(data.object.title);
			$("#abstract").val(data.object.abstractContent);
			var label = data.object.label;
			$('.chips-initial').material_chip({
				data: [{
					tag: 'Apple',
				}, {
					tag: 'Microsoft',
				}, {
					tag: 'Google',
				}],
			});

			var recommand = data.object.recommand;
			if (recommand == 0){
				$("#recommand2").attr("checked","checked");
			}
			else if (recommand == 1){ //推荐
				$("#recommand1").attr("checked","checked");
			}
			categoryVue.selected = data.object.categoryId;
			$("#uploadThumb").attr('src', data.object.thumb);
			$("#uploadBg").attr('src', data.object.bgUrl);
			ue.setContent(data.object.content);

			thumbImgUrl = data.object.thumb;
			bgImgUrl = data.object.bgUrl;
			$("#circleProgress").hide();

		},
		statusCode: {
			404: function() {
				Materialize.toast('没有加载到相应页面!', 4000);
			},
			500: function() {
				Materialize.toast('服务器内部错误!', 4000);
			}
		}
	});
}

$(document).ready(function() {

	$("#ossThumbProgress").hide();
	$("#ossBgProgress").hide();

	var ue = UE.getEditor('myEditor');

	(function($) {
		$.getUrlParam = function(name) {
			var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
			var r = window.location.search.substr(1).match(reg);
			if(r != null) return unescape(r[2]);
			return null;
		}
	})(jQuery);

	$('.chips-initial').material_chip({
		data: [{
			tag: '新通道',
		}],
	});

	var id = $.getUrlParam('id');
	console.log("id:"+id);

	if(id > 0) { //编辑操作
		loadingArticleById(id,ue);
	}

	$("#submitBtn").click(function() {
		var recommand = $('input:radio:checked').val();
		var htmlContent = ue.getContent();

		let title = $("#title").val();
		let abstractData = $("#abstract").val();
		let tag = $('.chips-initial').material_chip('data');
		console.log(tag);
		var label = "";
		if (tag.length > 0){
			tag.forEach(function(object,i){
			    console.log(object.tag);
			    label = label + object.tag + ",";
			})

		}

		if(title == "") {
			Materialize.toast('标题不能为空!', 4000);
			return;
		}

		if(abstractData == "") {
			Materialize.toast('描述不能为空!', 4000);
			return;
		}

		if(categoryId == 0) {
			Materialize.toast('文章类别没选!', 4000);
			return;
		}

		if(tag.length < 1) {
			Materialize.toast('文章标签不能为空!', 4000);
			return;
		}
		let requestData = {
			"title": title,
			"abstractContent": abstractData,
			"categoryId": categoryId,
			"label": label,
			"recommand": recommand,
			"thumb": thumbImgUrl,
			"bgUrl": bgImgUrl,
			"type": 0,
			"content": htmlContent
		};

		var requestUrl = "";

		if(insertOrUpdate == 0) {
			//插入数据
			requestUrl = "../article/create";
		} else if(insertOrUpdate == 1) {

			//更新数据
			requestData.id = updateId;
			requestUrl = "../article/update";
		}

		$.ajax({

			type: "POST",
			url: requestUrl,
			contentType: 'application/json',
			dataType: "json",
			data: JSON.stringify(requestData),
			beforeSend: function() {
				$("#circleProgress").show();
			},
			success: function(data) {
				//将数据通过vue.js更新到数据列表
				Materialize.toast('操作成功!', 4000);
				$("#circleProgress").hide();
				$("#addPanel").hide();
				$("#managePanel").empty();
				$("#managePanel").load("contentManage.html");
			},
			statusCode: {
				404: function() {
					Materialize.toast('没有加载到相应页面!', 4000);
				},
				500: function() {
					Materialize.toast('服务器内部错误!', 4000);
				}
			}
		});
	});

	$("#browserBtn").click(function() {
		var recommand = $('input:radio:checked').val();
		var htmlContent = ue.getContent();

		let title = $("#title").val();
		let abstractData = $("#abstract").val();
		let tag = $('.chips-initial').material_chip('data');

		if(title == "") {
			Materialize.toast('标题不能为空!', 4000);
			return;
		}

		if(abstractData == "") {
			Materialize.toast('描述不能为空!', 4000);
			return;
		}

		if(categoryId == 0) {
			Materialize.toast('文章类别没选!', 4000);
			return;
		}

		if(tag == "") {
			Materialize.toast('文章标签不能为空!', 4000);
			return;
		}

		if(htmlContent == "") {
			Materialize.toast('文章内容不能为空!', 4000);
			return;
		}
		window.localStorage.setItem("htmlContent", htmlContent);

		window.open("articlePreview.html?title=" + title + "&bgImage=" + bgImgUrl);

	});

	$("#cancelBtn").click(function() {
		$("#managePanel").empty();
		$("#managePanel").load("contentManage.html");
	});
});<commit_msg>fix bugs<commit_after>var thumbImgUrl = "";
var bgImgUrl = "";
var categoryId = 1;
var insertOrUpdate = 0;
var categoryVue;
/**
 * 初始化下拉列表框
 */
$.getJSON("../category/getCategoryByPage", {
	offset: 0,
	limit: 1000
}, function(data) {
	categoryVue = new Vue({
		el: '#dropdown',
		data: {
			selected: '',
			menus: data.object.list
		},
		mounted: function() {
			$('#dropdown select').material_select();
			$('#categorySelect').change(function() {
				categoryVue.selected = $('#categorySelect').val();
			});

		},
		watch: {
			selected: function(value) {
				searchOrSelect = 0;
				categoryId = value;
				console.log(categoryId);
			}
		}
	})
});

var thumbUploader = new plupload.Uploader({
	runtimes: 'html5,flash,silverlight,html4',
	browse_button: 'uploadThumb',
	//multi_selection: false,
	//container: document.getElementById('container'),
	flash_swf_url: '../resources/js/plupload-2.3.1/Moxie.swf',
	silverlight_xap_url: '../resources/js/plupload-2.3.1/Moxie.xap',
	url: 'http://oss.aliyuncs.com',

	filters: {
		mime_types: [ //只允许上传图片和zip,rar文件
			{
				title: "Image files",
				extensions: "jpg,jpeg,png",
				mimeTypes: 'image/jpg,image/jpeg,image/png'
			}
		],
		max_file_size: '1mb', //最大只能上传10mb的文件
		prevent_duplicates: true
		//不允许选取重复文件
	},

	init: {
		PostInit: function() {
			$("#console").html('');
			serverUrl = '../uploadKey/3';
		},

		FilesAdded: function(up, files) {
			$("#ossThumbProgress").show();
			plupload.each(files,
				function(file) {
					$("#thumbFileDescribe").append(file.name + ' (' + plupload.formatSize(file.size) + ') ');
				});
			$("#ossBgfile .determinate").show();
			set_upload_param(thumbUploader, '', false);
		},

		BeforeUpload: function(up, file) {

			set_upload_param(up, file.name, true);
		},

		UploadProgress: function(up, file) {
			$("#thumbFileCompletePersent").html(file.percent + '% ,');
			$("#ossThumbfile .determinate").width(file.percent + '%');
		},

		FileUploaded: function(up, file, info) {
			if(info.status == 200) {
				$("#thumbFileDescribe").innerHTML = '，上传成功！';
				thumbImgUrl = host + "/" + get_uploaded_object_name(file.name) + "?x-oss-process=style/thumb-300";
				$("#uploadThumb").attr('src', thumbImgUrl);

			} else {
				$("#thumbFileDescribe").innerHTML = info.response;
			}
		},

		Error: function(up, err) {
			if(err.code == -600) {
				$("#thumbConsole").html('选择的文件太大了，不能超过1M!');

			} else if(err.code == -601) {
				$("#thumbConsole").html('选择的文件后缀不对!');

			} else if(err.code == -602) {
				$("#thumbConsole").html("这个文件已经上传过一遍了");
			} else {
				$("#thumbConsole").html("上传出错！");
			}
		}
	}
});

thumbUploader.init();

var bgUploader = new plupload.Uploader({
	runtimes: 'html5,flash,silverlight,html4',
	browse_button: 'uploadBg',
	//multi_selection: false,
	//container: document.getElementById('container'),
	flash_swf_url: '../resources/js/plupload-2.3.1/Moxie.swf',
	silverlight_xap_url: '../resources/js/plupload-2.3.1/Moxie.xap',
	url: 'http://oss.aliyuncs.com',

	filters: {
		mime_types: [ //只允许上传图片和zip,rar文件
			{
				title: "Image files",
				extensions: "jpg,jpeg,png",
				mimeTypes: 'image/jpg,image/jpeg,image/png'
			}
		],
		max_file_size: '10mb', //最大只能上传10mb的文件
		prevent_duplicates: true
		//不允许选取重复文件
	},

	init: {
		PostInit: function() {
			$("#console").html('');
			serverUrl = '../uploadKey/3';
		},

		FilesAdded: function(up, files) {
			$("#ossBgfile .progress").show();
			plupload.each(files,
				function(file) {
					$("#bgFileDescribe").append(file.name + ' (' + plupload.formatSize(file.size) + ') ');
				});
			$("#ossBgProgress").show();
			set_upload_param(bgUploader, '', false);
		},

		BeforeUpload: function(up, file) {

			set_upload_param(up, file.name, true);
		},

		UploadProgress: function(up, file) {
			$("#bgFileCompletePersent").html(file.percent + '% ,');
			$("#ossBgfile .determinate").width(file.percent + '%');
		},

		FileUploaded: function(up, file, info) {
			if(info.status == 200) {
				$("#bgFileDescribe").innerHTML = '，上传成功！';
				bgImgUrl = host + "/" + get_uploaded_object_name(file.name) + "?x-oss-process=style/thumb-300";
				$("#uploadBg").attr('src', bgImgUrl);

			} else {
				$("#bgFileDescribe").innerHTML = info.response;
			}
		},

		Error: function(up, err) {
			if(err.code == -600) {
				$("#bgConsole").html('选择的文件太大了，不能超过10M!');

			} else if(err.code == -601) {
				$("#bgConsole").html('选择的文件后缀不对!');

			} else if(err.code == -602) {
				$("#bgConsole").html("这个文件已经上传过一遍了");
			} else {
				$("#bgConsole").html("上传出错！");
			}
		}
	}
});

bgUploader.init();

function loadingArticleById(id,ue) {

	$.ajax({
		type: "GET",
		url: "../article/getArticleDetailById/" + id,
		contentType: 'application/json',
		dataType: "json",
		beforeSend: function() {
			$("#circleProgress").show();
		},
		success: function(data) {
			$("#title").val(data.object.title);
			$("#title").addClass('active');
			$("#abstract").val(data.object.abstractContent);
			$("#abstract").addClass('active');
			var label = data.object.label;
			var labelArray = label.split(',');
			var labelData = [];
			labelArray.forEach(function(tag,i){
				var obj = {'tag':tag};
			    labelData.push(obj);
			})

			$('.chips-initial').material_chip({
				data:labelData,
			});

			var recommand = data.object.recommand;
			if (recommand == 0){
				$("#recommand2").attr("checked","checked");
			}
			else if (recommand == 1){ //推荐
				$("#recommand1").attr("checked","checked");
			}

			$("#categorySelect option[value='"+data.object.categoryId+"']").attr("selected", true);

			$("#uploadThumb").attr('src', data.object.thumb);
			$("#uploadBg").attr('src', data.object.bgUrl);
			ue.setContent(data.object.content);

			thumbImgUrl = data.object.thumb;
			bgImgUrl = data.object.bgUrl;
			$("#circleProgress").hide();

		},
		statusCode: {
			404: function() {
				Materialize.toast('没有加载到相应页面!', 4000);
			},
			500: function() {
				Materialize.toast('服务器内部错误!', 4000);
			}
		}
	});
}

$(document).ready(function() {

	$("#ossThumbProgress").hide();
	$("#ossBgProgress").hide();

	var ue = UE.getEditor('myEditor');

	$('.chips-initial').material_chip({
		data: [{
			tag: '新通道',
		}],
	});

	var id = window.localStorage.getItem("articleId");

	if(id > 0) { //编辑操作
		loadingArticleById(id,ue);
	}

	$("#submitBtn").click(function() {
		var recommand = $('input:radio:checked').val();
		var htmlContent = ue.getContent();

		let title = $("#title").val();
		let abstractData = $("#abstract").val();
		let tag = $('.chips-initial').material_chip('data');

		var label = "";
		if (tag.length > 0){
			tag.forEach(function(object,i){
			    label = label + object.tag + ",";
			})
		}

		if(title == "") {
			Materialize.toast('标题不能为空!', 4000);
			return;
		}

		if(abstractData == "") {
			Materialize.toast('描述不能为空!', 4000);
			return;
		}

		if(categoryId == 0) {
			Materialize.toast('文章类别没选!', 4000);
			return;
		}

		if(tag.length < 1) {
			Materialize.toast('文章标签不能为空!', 4000);
			return;
		}
		let requestData = {
			"title": title,
			"abstractContent": abstractData,
			"categoryId": categoryId,
			"label": label,
			"recommand": recommand,
			"thumb": thumbImgUrl,
			"bgUrl": bgImgUrl,
			"type": 0,
			"content": htmlContent
		};

		var requestUrl = "";

		if(insertOrUpdate == 0) {
			//插入数据
			requestUrl = "../article/create";
		} else if(insertOrUpdate == 1) {

			//更新数据
			requestData.id = updateId;
			requestUrl = "../article/update";
		}

		$.ajax({

			type: "POST",
			url: requestUrl,
			contentType: 'application/json',
			dataType: "json",
			data: JSON.stringify(requestData),
			beforeSend: function() {
				$("#circleProgress").show();
			},
			success: function(data) {
				//将数据通过vue.js更新到数据列表
				Materialize.toast('操作成功!', 4000);
				$("#circleProgress").hide();
				$("#addPanel").hide();
				$("#managePanel").empty();
				$("#managePanel").load("contentManage.html");
			},
			statusCode: {
				404: function() {
					Materialize.toast('没有加载到相应页面!', 4000);
				},
				500: function() {
					Materialize.toast('服务器内部错误!', 4000);
				}
			}
		});
	});

	$("#browserBtn").click(function() {
		var recommand = $('input:radio:checked').val();
		var htmlContent = ue.getContent();

		let title = $("#title").val();
		let abstractData = $("#abstract").val();
		let tag = $('.chips-initial').material_chip('data');

		if(title == "") {
			Materialize.toast('标题不能为空!', 4000);
			return;
		}

		if(abstractData == "") {
			Materialize.toast('描述不能为空!', 4000);
			return;
		}

		if(categoryId == 0) {
			Materialize.toast('文章类别没选!', 4000);
			return;
		}

		if(tag == "") {
			Materialize.toast('文章标签不能为空!', 4000);
			return;
		}

		if(htmlContent == "") {
			Materialize.toast('文章内容不能为空!', 4000);
			return;
		}
		window.localStorage.setItem("htmlContent", htmlContent);

		window.open("articlePreview.html?title=" + title + "&bgImage=" + bgImgUrl);

	});

	$("#cancelBtn").click(function() {
		$("#managePanel").empty();
		$("#managePanel").load("contentManage.html");
	});
});<|endoftext|>