http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-htraced/src/web/lib/underscore-1.7.0.js ---------------------------------------------------------------------- diff --git a/htrace-htraced/src/web/lib/underscore-1.7.0.js b/htrace-htraced/src/web/lib/underscore-1.7.0.js deleted file mode 100644 index d5b3375..0000000 --- a/htrace-htraced/src/web/lib/underscore-1.7.0.js +++ /dev/null @@ -1,1416 +0,0 @@ -// Underscore.js 1.7.0 -// http://underscorejs.org -// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -(function() { - - // Baseline setup - // -------------- - - // Establish the root object, `window` in the browser, or `exports` on the server. - var root = this; - - // Save the previous value of the `_` variable. - var previousUnderscore = root._; - - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - - // Create quick reference variables for speed access to core prototypes. - var - push = ArrayProto.push, - slice = ArrayProto.slice, - concat = ArrayProto.concat, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeBind = FuncProto.bind; - - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for the old `require()` API. If we're in - // the browser, add `_` as a global object. - if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - - // Current version. - _.VERSION = '1.7.0'; - - // Internal function that returns an efficient (for current engines) version - // of the passed-in callback, to be repeatedly applied in other Underscore - // functions. - var createCallback = function(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: return function(value) { - return func.call(context, value); - }; - case 2: return function(value, other) { - return func.call(context, value, other); - }; - case 3: return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; - }; - - // A mostly-internal function to generate callbacks that can be applied - // to each element in a collection, returning the desired result â either - // identity, an arbitrary callback, a property matcher, or a property accessor. - _.iteratee = function(value, context, argCount) { - if (value == null) return _.identity; - if (_.isFunction(value)) return createCallback(value, context, argCount); - if (_.isObject(value)) return _.matches(value); - return _.property(value); - }; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles raw objects in addition to array-likes. Treats all - // sparse array-likes as if they were dense. - _.each = _.forEach = function(obj, iteratee, context) { - if (obj == null) return obj; - iteratee = createCallback(iteratee, context); - var i, length = obj.length; - if (length === +length) { - for (i = 0; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); - } - } - return obj; - }; - - // Return the results of applying the iteratee to each element. - _.map = _.collect = function(obj, iteratee, context) { - if (obj == null) return []; - iteratee = _.iteratee(iteratee, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - results = Array(length), - currentKey; - for (var index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - var reduceError = 'Reduce of empty array with no initial value'; - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. - _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) { - if (obj == null) obj = []; - iteratee = createCallback(iteratee, context, 4); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index = 0, currentKey; - if (arguments.length < 3) { - if (!length) throw new TypeError(reduceError); - memo = obj[keys ? keys[index++] : index++]; - } - for (; index < length; index++) { - currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; - - // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = function(obj, iteratee, memo, context) { - if (obj == null) obj = []; - iteratee = createCallback(iteratee, context, 4); - var keys = obj.length !== + obj.length && _.keys(obj), - index = (keys || obj).length, - currentKey; - if (arguments.length < 3) { - if (!index) throw new TypeError(reduceError); - memo = obj[keys ? keys[--index] : --index]; - } - while (index--) { - currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, predicate, context) { - var result; - predicate = _.iteratee(predicate, context); - _.some(obj, function(value, index, list) { - if (predicate(value, index, list)) { - result = value; - return true; - } - }); - return result; - }; - - // Return all the elements that pass a truth test. - // Aliased as `select`. - _.filter = _.select = function(obj, predicate, context) { - var results = []; - if (obj == null) return results; - predicate = _.iteratee(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(_.iteratee(predicate)), context); - }; - - // Determine whether all of the elements match a truth test. - // Aliased as `all`. - _.every = _.all = function(obj, predicate, context) { - if (obj == null) return true; - predicate = _.iteratee(predicate, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index, currentKey; - for (index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; - } - return true; - }; - - // Determine if at least one element in the object matches a truth test. - // Aliased as `any`. - _.some = _.any = function(obj, predicate, context) { - if (obj == null) return false; - predicate = _.iteratee(predicate, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index, currentKey; - for (index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; - } - return false; - }; - - // Determine if the array or object contains a given value (using `===`). - // Aliased as `include`. - _.contains = _.include = function(obj, target) { - if (obj == null) return false; - if (obj.length !== +obj.length) obj = _.values(obj); - return _.indexOf(obj, target) >= 0; - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - return (isFunc ? method : value[method]).apply(value, args); - }); - }; - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs) { - return _.filter(obj, _.matches(attrs)); - }; - - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matches(attrs)); - }; - - // Return the maximum element (or element-based computation). - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = obj.length === +obj.length ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value > result) { - result = value; - } - } - } else { - iteratee = _.iteratee(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = obj.length === +obj.length ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value < result) { - result = value; - } - } - } else { - iteratee = _.iteratee(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Shuffle a collection, using the modern version of the - // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/FisherâYates_shuffle). - _.shuffle = function(obj) { - var set = obj && obj.length === +obj.length ? obj : _.values(obj); - var length = set.length; - var shuffled = Array(length); - for (var index = 0, rand; index < length; index++) { - rand = _.random(0, index); - if (rand !== index) shuffled[index] = shuffled[rand]; - shuffled[rand] = set[index]; - } - return shuffled; - }; - - // Sample **n** random values from a collection. - // If **n** is not specified, returns a single random element. - // The internal `guard` argument allows it to work with `map`. - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (obj.length !== +obj.length) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; - } - return _.shuffle(obj).slice(0, Math.max(0, n)); - }; - - // Sort the object's values by a criterion produced by an iteratee. - _.sortBy = function(obj, iteratee, context) { - iteratee = _.iteratee(iteratee, context); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iteratee(value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(behavior) { - return function(obj, iteratee, context) { - var result = {}; - iteratee = _.iteratee(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) result[key].push(value); else result[key] = [value]; - }); - - // Indexes the object's values by a criterion, similar to `groupBy`, but for - // when you know that your index values will be unique. - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) result[key]++; else result[key] = 1; - }); - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = _.iteratee(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = array.length; - while (low < high) { - var mid = low + high >>> 1; - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - - // Safely create a real, live array from anything iterable. - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (obj.length === +obj.length) return _.map(obj, _.identity); - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) return 0; - return obj.length === +obj.length ? obj.length : _.keys(obj).length; - }; - - // Split a collection into two arrays: one whose elements all satisfy the given - // predicate, and one whose elements all do not satisfy the predicate. - _.partition = function(obj, predicate, context) { - predicate = _.iteratee(predicate, context); - var pass = [], fail = []; - _.each(obj, function(value, key, obj) { - (predicate(value, key, obj) ? pass : fail).push(value); - }); - return [pass, fail]; - }; - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[0]; - if (n < 0) return []; - return slice.call(array, 0, n); - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. The **guard** check allows it to work with - // `_.map`. - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. The **guard** check allows it to work with `_.map`. - _.last = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[array.length - 1]; - return slice.call(array, Math.max(array.length - n, 0)); - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. The **guard** - // check allows it to work with `_.map`. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, _.identity); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, output) { - if (shallow && _.every(input, _.isArray)) { - return concat.apply(output, input); - } - for (var i = 0, length = input.length; i < length; i++) { - var value = input[i]; - if (!_.isArray(value) && !_.isArguments(value)) { - if (!strict) output.push(value); - } else if (shallow) { - push.apply(output, value); - } else { - flatten(value, shallow, strict, output); - } - } - return output; - }; - - // Flatten out an array, either recursively (by default), or just one level. - _.flatten = function(array, shallow) { - return flatten(array, shallow, false, []); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (array == null) return []; - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = _.iteratee(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = array.length; i < length; i++) { - var value = array[i]; - if (isSorted) { - if (!i || seen !== value) result.push(value); - seen = value; - } else if (iteratee) { - var computed = iteratee(value, i, array); - if (_.indexOf(seen, computed) < 0) { - seen.push(computed); - result.push(value); - } - } else if (_.indexOf(result, value) < 0) { - result.push(value); - } - } - return result; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(flatten(arguments, true, true, [])); - }; - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - if (array == null) return []; - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = array.length; i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) continue; - for (var j = 1; j < argsLength; j++) { - if (!_.contains(arguments[j], item)) break; - } - if (j === argsLength) result.push(item); - } - return result; - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = flatten(slice.call(arguments, 1), true, true, []); - return _.filter(array, function(value){ - return !_.contains(rest, value); - }); - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function(array) { - if (array == null) return []; - var length = _.max(arguments, 'length').length; - var results = Array(length); - for (var i = 0; i < length; i++) { - results[i] = _.pluck(arguments, i); - } - return results; - }; - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - if (list == null) return {}; - var result = {}; - for (var i = 0, length = list.length; i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // Return the position of the first occurrence of an item in an array, - // or -1 if the item is not included in the array. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i = 0, length = array.length; - if (isSorted) { - if (typeof isSorted == 'number') { - i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; - } else { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; - } - } - for (; i < length; i++) if (array[i] === item) return i; - return -1; - }; - - _.lastIndexOf = function(array, item, from) { - if (array == null) return -1; - var idx = array.length; - if (typeof from == 'number') { - idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1); - } - while (--idx >= 0) if (array[idx] === item) return idx; - return -1; - }; - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (arguments.length <= 1) { - stop = start || 0; - start = 0; - } - step = step || 1; - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Reusable constructor function for prototype setting. - var Ctor = function(){}; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = function(func, context) { - var args, bound; - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); - args = slice.call(arguments, 2); - bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - Ctor.prototype = func.prototype; - var self = new Ctor; - Ctor.prototype = null; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (_.isObject(result)) return result; - return self; - }; - return bound; - }; - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. _ acts - // as a placeholder, allowing any combination of arguments to be pre-filled. - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - return function() { - var position = 0; - var args = boundArgs.slice(); - for (var i = 0, length = args.length; i < length; i++) { - if (args[i] === _) args[i] = arguments[position++]; - } - while (position < arguments.length) args.push(arguments[position++]); - return func.apply(this, args); - }; - }; - - // Bind a number of an object's methods to that object. Remaining arguments - // are the method names to be bound. Useful for ensuring that all callbacks - // defined on an object belong to it. - _.bindAll = function(obj) { - var i, length = arguments.length, key; - if (length <= 1) throw new Error('bindAll must be passed function names'); - for (i = 1; i < length; i++) { - key = arguments[i]; - obj[key] = _.bind(obj[key], obj); - } - return obj; - }; - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = hasher ? hasher.apply(this, arguments) : key; - if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ - return func.apply(null, args); - }, wait); - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = function(func) { - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); - }; - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - if (!options) options = {}; - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; - - var later = function() { - var last = _.now() - timestamp; - - if (last < wait && last > 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - if (!timeout) context = args = null; - } - } - }; - - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - context = args = null; - } - - return result; - }; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - - // Returns a negated version of the passed-in predicate. - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); - return result; - }; - }; - - // Returns a function that will only be executed after being called N times. - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Returns a function that will only be executed before being called N times. - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } else { - func = null; - } - return memo; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = _.partial(_.before, 2); - - // Object Functions - // ---------------- - - // Retrieve the names of an object's properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [keys[i], obj[keys[i]]]; - } - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; - } - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = function(obj) { - if (!_.isObject(obj)) return obj; - var source, prop; - for (var i = 1, length = arguments.length; i < length; i++) { - source = arguments[i]; - for (prop in source) { - if (hasOwnProperty.call(source, prop)) { - obj[prop] = source[prop]; - } - } - } - return obj; - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(obj, iteratee, context) { - var result = {}, key; - if (obj == null) return result; - if (_.isFunction(iteratee)) { - iteratee = createCallback(iteratee, context); - for (key in obj) { - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } - } else { - var keys = concat.apply([], slice.call(arguments, 1)); - obj = new Object(obj); - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (key in obj) result[key] = obj[key]; - } - } - return result; - }; - - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj, iteratee, context) { - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - } else { - var keys = _.map(concat.apply([], slice.call(arguments, 1)), String); - iteratee = function(value, key) { - return !_.contains(keys, key); - }; - } - return _.pick(obj, iteratee, context); - }; - - // Fill in a given object with default properties. - _.defaults = function(obj) { - if (!_.isObject(obj)) return obj; - for (var i = 1, length = arguments.length; i < length; i++) { - var source = arguments[i]; - for (var prop in source) { - if (obj[prop] === void 0) obj[prop] = source[prop]; - } - } - return obj; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a === 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) return false; - switch (className) { - // Strings, numbers, regular expressions, dates, and booleans are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN - if (+a !== +a) return +b !== +b; - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - } - if (typeof a != 'object' || typeof b != 'object') return false; - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) return bStack[length] === b; - } - // Objects with different constructors are not equivalent, but `Object`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if ( - aCtor !== bCtor && - // Handle Object.create(x) cases - 'constructor' in a && 'constructor' in b && - !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - ) { - return false; - } - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - var size, result; - // Recursively compare objects and arrays. - if (className === '[object Array]') { - // Compare array lengths to determine if a deep comparison is necessary. - size = a.length; - result = size === b.length; - if (result) { - // Deep compare the contents, ignoring non-numeric properties. - while (size--) { - if (!(result = eq(a[size], b[size], aStack, bStack))) break; - } - } - } else { - // Deep compare objects. - var keys = _.keys(a), key; - size = keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - result = _.keys(b).length === size; - if (result) { - while (size--) { - // Deep compare each member - key = keys[size]; - if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; - } - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return result; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b, [], []); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0; - for (var key in obj) if (_.has(obj, key)) return false; - return true; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) === '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, 'callee'); - }; - } - - // Optimize `isFunction` if appropriate. Work around an IE 11 bug. - if (typeof /./ !== 'function') { - _.isFunction = function(obj) { - return typeof obj == 'function' || false; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj !== +obj; - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iteratees. - _.identity = function(value) { - return value; - }; - - // Predicate-generating functions. Often useful outside of Underscore. - _.constant = function(value) { - return function() { - return value; - }; - }; - - _.noop = function(){}; - - _.property = function(key) { - return function(obj) { - return obj[key]; - }; - }; - - // Returns a predicate for checking whether an object has a given set of `key:value` pairs. - _.matches = function(attrs) { - var pairs = _.pairs(attrs), length = pairs.length; - return function(obj) { - if (obj == null) return !length; - obj = new Object(obj); - for (var i = 0; i < length; i++) { - var pair = pairs[i], key = pair[0]; - if (pair[1] !== obj[key] || !(key in obj)) return false; - } - return true; - }; - }; - - // Run a function **n** times. - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = createCallback(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - - // A (possibly faster) way to get the current timestamp as an integer. - _.now = Date.now || function() { - return new Date().getTime(); - }; - - // List of HTML entities for escaping. - var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' - }; - var unescapeMap = _.invert(escapeMap); - - // Functions for escaping and unescaping strings to/from HTML interpolation. - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped - var source = '(?:' + _.keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - - // If the value of the named `property` is a function then invoke it with the - // `object` as context; otherwise, return it. - _.result = function(object, property) { - if (object == null) return void 0; - var value = object[property]; - return _.isFunction(value) ? object[property]() : value; - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\u2028|\u2029/g; - - var escapeChar = function(match) { - return '\\' + escapes[match]; - }; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - // NB: `oldSettings` only exists for backwards compatibility. - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escaper, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offest. - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - try { - var render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled source as a convenience for precompilation. - var argument = settings.variable || 'obj'; - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function. Start chaining a wrapped Underscore object. - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var result = function(obj) { - return this._chain ? _(obj).chain() : obj; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result.call(this, func.apply(_, args)); - }; - }); - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; - return result.call(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - _.each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result.call(this, method.apply(this._wrapped, arguments)); - }; - }); - - // Extracts the result from a wrapped and chained object. - _.prototype.value = function() { - return this._wrapped; - }; - - // AMD registration happens at the end for compatibility with AMD loaders - // that may not enforce next-turn semantics on modules. Even though general - // practice for AMD registration is to be anonymous, underscore registers - // as a named module because, like jQuery, it is a base library that is - // popular enough to be bundled in a third party lib, but not be part of - // an AMD load request. Those cases could generate an error when an - // anonymous define() is called outside of a loader request. - if (typeof define === 'function' && define.amd) { - define('underscore', [], function() { - return _; - }); - } -}.call(this)); \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/README.md ---------------------------------------------------------------------- diff --git a/htrace-webapp/README.md b/htrace-webapp/README.md new file mode 100644 index 0000000..3f11b79 --- /dev/null +++ b/htrace-webapp/README.md @@ -0,0 +1,21 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +htrace-webapp +============ + +htrace-webapp provides a web interface to an htrace server. http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/pom.xml ---------------------------------------------------------------------- diff --git a/htrace-webapp/pom.xml b/htrace-webapp/pom.xml new file mode 100644 index 0000000..b5cd156 --- /dev/null +++ b/htrace-webapp/pom.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor +license agreements. See the NOTICE file distributed with this work for additional +information regarding copyright ownership. The ASF licenses this file to +You under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of +the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required +by applicable law or agreed to in writing, software distributed under the +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <artifactId>htrace-webapp</artifactId> + <packaging>war</packaging> + + <parent> + <artifactId>htrace</artifactId> + <groupId>org.apache.htrace</groupId> + <version>3.3.0-incubating-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <name>htrace-webapp</name> + <description>A webapp for an htrace server</description> + <url>http://incubator.apache.org/projects/htrace.html</url> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <configuration> + <webXml>src/main/web/WEB-INF/web.xml</webXml> + </configuration> + </plugin> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <descriptorRefs> + <descriptorRef>project</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + </plugin> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-gpg-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.rat</groupId> + <artifactId>apache-rat-plugin</artifactId> + </plugin> + <plugin> + <!-- explicitly define maven-deploy-plugin after other to force exec order --> + <artifactId>maven-deploy-plugin</artifactId> + </plugin> + </plugins> + </build> + + <dependencies> + <!-- Module deps. --> + <dependency> + <groupId>org.apache.htrace</groupId> + <artifactId>htrace-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.htrace</groupId> + <artifactId>htrace-core</artifactId> + <version>${project.version}</version> + <classifier>tests</classifier> + <scope>test</scope> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>dist</id> + <build> + <plugins> + <plugin> + <!--Make it so assembly:single does nothing in here--> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <skipAssembly>true</skipAssembly> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/WEB-INF/web.xml b/htrace-webapp/src/main/web/WEB-INF/web.xml new file mode 100644 index 0000000..38c7a98 --- /dev/null +++ b/htrace-webapp/src/main/web/WEB-INF/web.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor +license agreements. See the NOTICE file distributed with this work for additional +information regarding copyright ownership. The ASF licenses this file to +You under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of +the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required +by applicable law or agreed to in writing, software distributed under the +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. --> + +<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> + + <display-name>HTrace</display-name> +<description>WebApp that goes against an htrace server. +</description> +</web-app> http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/about_view.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/about_view.js b/htrace-webapp/src/main/web/app/about_view.js new file mode 100644 index 0000000..7dfe868 --- /dev/null +++ b/htrace-webapp/src/main/web/app/about_view.js @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; +htrace.AboutView = Backbone.View.extend({ + render: function() { + this.$el.html(_.template($("#about-view-template").html()) + ({ model : this.model })); + console.log("AboutView#render"); + return this; + }, + + close: function() { + console.log("AboutView#close") + this.undelegateEvents(); + } +}); http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/modal.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/modal.js b/htrace-webapp/src/main/web/app/modal.js new file mode 100644 index 0000000..91d55fe --- /dev/null +++ b/htrace-webapp/src/main/web/app/modal.js @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +// Show a modal dialog box with a warning message. +htrace.showModalWarning = function(title, body) { + var html = _.template($("#modal-warning-template").html()) + ({ title: title, body: body }); + htrace.showModal(html); +} + +// Show a modal dialog box. +htrace.showModal = function(html) { + var el = $("#modal"); + el.html(html); + el.modal(); +} http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/predicate.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/predicate.js b/htrace-webapp/src/main/web/app/predicate.js new file mode 100644 index 0000000..87a5602 --- /dev/null +++ b/htrace-webapp/src/main/web/app/predicate.js @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +htrace.checkStringIsPositiveWholeNumber = function(val) { + if (!val.match(/^[0-9]([0-9]*)$/)) { + if (!val.match(/[^\s]/)) { + throw "You entered an empty string into a numeric field."; + } + throw "Non-numeric characters found."; + } +}; + +htrace.checkStringIsNotEmpty = function(val) { + if (!val.match(/[^\s]/)) { + throw "You entered an empty string into a text field."; + } +}; + +// Predicate type +htrace.PType = Backbone.Model.extend({ + initialize: function(options) { + this.name = options.name; + this.field = options.field; + this.op = options.op; + }, + + // Try to normalize a value of this type into something htraced can accept. + // Returns a string containing the normalized value on success. Throws a + // string explaining the parse error otherwise. + // Dates are represented by milliseconds since the epoch; span ids don't start + // with 0x. + normalize: function(val) { + switch (this.field) { + case "begin": + return htrace.parseDate(val).valueOf().toString(); + case "end": + return htrace.parseDate(val).valueOf().toString(); + case "description": + htrace.checkStringIsNotEmpty(val); + return val; + case "duration": + htrace.checkStringIsPositiveWholeNumber(val); + return val; + case "spanid": + return htrace.normalizeSpanId(val); + default: + return "Normalization not implemented for field '" + this.field + "'"; + } + }, + + getDefaultValue: function() { + switch (this.field) { + case "begin": + return htrace.dateToString(moment()); + case "end": + return htrace.dateToString(moment()); + case "description": + return ""; + case "duration": + return "0"; + case "spanid": + return ""; + default: + return "(unknown)"; + } + } +}); + +htrace.parsePType = function(name) { + switch (name) { + case "Began after": + return new htrace.PType({name: name, field:"begin", op:"gt"}); + case "Began at or before": + return new htrace.PType({name: name, field:"begin", op:"le"}); + case "Ended after": + return new htrace.PType({name: name, field:"end", op:"gt"}); + case "Ended at or before": + return new htrace.PType({name: name, field:"end", op:"le"}); + case "Description contains": + return new htrace.PType({name: name, field:"description", op:"cn"}); + case "Description is exactly": + return new htrace.PType({name: name, field:"description", op:"eq"}); + case "Duration is longer than": + return new htrace.PType({name: name, field:"duration", op:"gt"}); + case "Duration is at most": + return new htrace.PType({name: name, field:"duration", op:"le"}); + case "Span ID is": + return new htrace.PType({name: name, field:"spanid", op:"eq"}); + default: + return null + } +}; + +htrace.Predicate = function(options) { + this.op = options.ptype.op; + this.field = options.ptype.field; + this.val = options.val; + return this; +}; http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/predicate_view.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/predicate_view.js b/htrace-webapp/src/main/web/app/predicate_view.js new file mode 100644 index 0000000..aefe896 --- /dev/null +++ b/htrace-webapp/src/main/web/app/predicate_view.js @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +htrace.PredicateView = Backbone.View.extend({ + initialize: function(options) { + this.el = options.el; + this.index = options.index; + this.ptype = options.ptype; + this.searchView = options.searchView; + }, + + events: { + "click .closeButton": "remove", + }, + + render: function() { + this.$el.html(_.template($("#predicate-template").html()) + ({ desc: this.ptype.name, id: this.index })) + if (this.getText() === "") { + $(this.$el).find(".form-control").val(this.ptype.getDefaultValue()); + } + console.log(this.toString() + "#render"); + return this; + }, + + // Handle the user removing this predicate. + remove: function() { + this.searchView.removePredicateView(this); + Backbone.View.prototype.remove.apply(this, arguments); + }, + + // Get the text which the user has entered in. + getText: function() { + return $(this.$el).find(".form-control").val().trim(); + }, + + // Get the predicate expressed by this view. + // Throw an exception if the predicate can't be parsed. + getPredicate: function() { + return new htrace.Predicate({ + ptype: this.ptype, + val: this.ptype.normalize(this.getText()) + }); + }, + + toString: function() { + return "PredicateView(this.el=" + this.el + ", this.index=" + + this.index + ", this.ptype='" + this.ptype.name + "')"; + } +}); http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/query_results.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/query_results.js b/htrace-webapp/src/main/web/app/query_results.js new file mode 100644 index 0000000..dc37e1e --- /dev/null +++ b/htrace-webapp/src/main/web/app/query_results.js @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +htrace.QueryResults = Backbone.Collection.extend({ + // The query results are spans. + model: htrace.Span, + + initialize: function(options) { + this.queryJson = options.queryJson; + }, + + url: function() { + return "query?query=" + this.queryString(); + }, + + parse: function(response, xhr) { + return response; + }, + + prettyQueryString: function() { + return JSON.stringify(this.queryJson, null, 2); + }, + + queryString: function() { + return JSON.stringify(this.queryJson); + } +}); http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/router.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/router.js b/htrace-webapp/src/main/web/app/router.js new file mode 100644 index 0000000..607da44 --- /dev/null +++ b/htrace-webapp/src/main/web/app/router.js @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +htrace.HTraceRouter = Backbone.Router.extend({ + "routes": { + "": "empty", + "about": "about", + "search": "search", + "*unknown": "unknown" + }, + + empty: function() { + console.log("Redirecting to #about."); + Backbone.history.navigate("about", {"trigger": true, "replace": true}); + }, + + about: function() { + console.log("Visiting #about."); + serverInfo = new htrace.ServerInfo(); + var router = this; + serverInfo.fetch({ + "success": function(model, response, options) { + router.switchView(new htrace.AboutView({model: serverInfo, el: "#app"})); + router.activateNavBarEntry("about") + }, + "error": function(model, response, options) { + window.alert("Failed to fetch htraced server info via GET " + + "/server/info: " + JSON.stringify(response)); + } + }); + }, + + search: function() { + console.log("Visiting #search."); + this.switchView(new htrace.SearchView({el : "#app"})); + htrace.router.activateNavBarEntry("search"); + }, + + unknown: function() { + console.log("Unknown route " + Backbone.history.getFragment() + ".") + }, + + "switchView": function(view) { + this.view && this.view.close(); + this.view = view; + this.view.render(); + }, + + "activateNavBarEntry": function(id) { + $(".nav").find(".active").removeClass("active"); + $(".nav").find("#" + id).addClass("active"); + } +}); + +htrace.router = new htrace.HTraceRouter(); +Backbone.history.start(); http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/search_result.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/search_result.js b/htrace-webapp/src/main/web/app/search_result.js new file mode 100644 index 0000000..9798ad7 --- /dev/null +++ b/htrace-webapp/src/main/web/app/search_result.js @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +// A pair of span trees: one going up, and the other going down. +// This represents a single search result. +htrace.SearchResult = Backbone.Model.extend({ + initialize: function(options) { + this.set("childrenRoot", { + root: options.span, + contents: null, + }); + this.set("childrenRoot", { + root: options.span, + contents: null, + }); + + this.set("parentsRoot", options.span); + }, + + getBegin: function() { + var begin = this.get("span").get("begin"); + var children = this.get("children"); + for (var childIdx = 0; childIdx < children.length; childIdx++) { + begin = Math.min(begin, children[childIdx].getBegin()); + } + return begin; + }, + + getEnd: function() { + var end = this.get("span").get("end"); + var children = this.get("children"); + for (var childIdx = 0; childIdx < children.length; childIdx++) { + end = Math.max(end, children[childIdx].getEnd()); + } + return end; + } +}); http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/search_results.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/search_results.js b/htrace-webapp/src/main/web/app/search_results.js new file mode 100644 index 0000000..25b18ae --- /dev/null +++ b/htrace-webapp/src/main/web/app/search_results.js @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +htrace.SearchResults = Backbone.Collection.extend({ + // The search results are span trees. + model: htrace.SpanTreeNode +}); http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/d0554d53/htrace-webapp/src/main/web/app/search_results_view.js ---------------------------------------------------------------------- diff --git a/htrace-webapp/src/main/web/app/search_results_view.js b/htrace-webapp/src/main/web/app/search_results_view.js new file mode 100644 index 0000000..111f530 --- /dev/null +++ b/htrace-webapp/src/main/web/app/search_results_view.js @@ -0,0 +1,361 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var htrace = htrace || {}; + +htrace.SearchResultsView = Backbone.View.extend({ + // The minimum time span we will allow between begin and end. + MINIMUM_TIME_SPAN: 100, + + begin: 0, + + end: this.MINIMUM_TIME_SPAN, + + initialize: function(options) { + this.searchResults = options.searchResults; + this.el = options.el; + this.listenTo(this.searchResults, 'add remove change reset', this.render); + + // Re-render the canvas when the window size changes. + // Add a debouncer delay to avoid spamming render requests. + var view = this; + $(window).on("resize", _.debounce(function() { + view.render(); + }, 250)); + }, + + // Get the canvas X coordinate of a mouse click from the absolute event + // coordinate. + getCanvasX: function(e) { + return e.pageX - $("#resultsCanvas").offset().left; + }, + + // Get the canvas Y coordinate of a mouse click from the absolute event + // coordinate. + getCanvasY: function(e) { + return e.pageY - $("#resultsCanvas").offset().top; + }, + + handleMouseDown: function(e) { + e.preventDefault(); + this.widgetManager.handle({ + type: "mouseDown", + x: this.getCanvasX(e), + y: this.getCanvasY(e) + }); + this.draw(); + }, + + handleMouseUp: function(e) { + e.preventDefault(); + this.widgetManager.handle({ + type: "mouseUp", + x: this.getCanvasX(e), + y: this.getCanvasY(e) + }); + this.draw(); + }, + + handleMouseOut: function(e) { + e.preventDefault(); + this.widgetManager.handle({ + type: "mouseOut" + }); + this.draw(); + }, + + handleMouseMove: function(e) { + e.preventDefault(); + this.widgetManager.handle({ + type: "mouseMove", + x: this.getCanvasX(e), + y: this.getCanvasY(e) + }); + this.draw(); + }, + + render: function() { + console.log("SearchResultsView#render."); + $(this.el).html(_.template($("#search-results-view-template").html())); + $('#selectedTime').attr('readonly', 'readonly'); + this.canvas = $("#resultsCanvas"); + this.ctx = this.canvas.get(0).getContext("2d"); + this.scaleCanvas(); + this.setupCoordinates(); + this.setupWidgets(); + this.draw(); + this.attachEvents(); + return this; + }, + + /* + * Compute the ratio to use between the size of the canvas (i.e. + * canvas.ctx.width, canvas.ctx.height) and the size in "HTML5 pixels." Note + * that 'HTML5 pixels" don't actually correspond to screen pixels. A line 1 + * "HTML5 pixel" wide actually takes up multiple scren pixels, etc. + * + * TODO: fix this to be sharper + */ + computeScaleFactor: function() { + var backingStoreRatio = this.ctx.backingStorePixelRatio || + this.ctx.mozBackingStorePixelRatio || + this.ctx.msBackingStorePixelRatio || + this.ctx.webkitBackingStorePixelRatio || + this.ctx.oBackingStorePixelRatio || + this.ctx.backingStorePixelRatio || 1; + return (window.devicePixelRatio || 1) / backingStoreRatio; + }, + + // Sets up the canvas size and scaling. + scaleCanvas: function() { + var cssX = this.canvas.parent().innerWidth(); + var cssY = $(window).innerHeight() - $("#header").innerHeight() - 50; + var ratio = this.computeScaleFactor(); + console.log("scaleCanvas: cssX=" + cssX + ", cssY=" + cssY + ", ratio=" + ratio); + this.maxX = cssX; + this.maxY = cssY; + $('#searchView').css('height', cssY + "px"); + $('#results').css('width', cssX + "px"); + $('#results').css('height', cssY + "px"); + $('#resultsView').css('width', cssX + "px"); + $('#resultsView').css('height', cssY + "px"); + $('#resultsDiv').css('width', cssX + "px"); + $('#resultsDiv').css('height', cssY + "px"); + $('#resultsCanvas').css('width', cssX + "px"); + $('#resultsCanvas').css('height', cssY + "px"); + this.ctx.canvas.width = cssX * ratio; + this.ctx.canvas.height = cssY * ratio; + this.ctx.scale(ratio, ratio); + }, + + // + // Set up the screen coordinates. + // + // 0 xB xD xS maxX + // +--------------+----------+--------------------+-----------+ + // |ProcessId | Buttons | Span Description | Scrollbar | + // +--------------+----------+--------------------+-----------+ + // + setupCoordinates: function() { + this.xB = Math.min(300, Math.floor(this.maxX / 5)); + this.xD = this.xB + Math.min(75, Math.floor(this.maxX / 20)); + var scrollBarWidth = Math.min(50, Math.floor(this.maxX / 10)); + this.xS = this.maxX - scrollBarWidth; + }, + + setupWidgets: function() { + this.widgetManager = new htrace.WidgetManager({searchResultsView: this}); + + // Create a SpanWidget for each span we know about + var spanWidgetHeight = Math.min(25, Math.floor(this.maxY / 32)); + var numResults = this.searchResults.size(); + var groupY = 0; + for (var i = 0; i < numResults; i++) { + var widget = new htrace.SpanGroupWidget({ + manager: this.widgetManager, + ctx: this.ctx, + span: this.searchResults.at(i), + x0: 0, + xB: this.xB, + xD: this.xD, + xF: this.xS, + y0: groupY, + begin: this.begin, + end: this.end, + spanWidgetHeight: spanWidgetHeight + }); + groupY = widget.yF; + } + + // Create the time cursor widget. + var selectedTime = this.begin; + if (this.timeCursor != null) { + selectedTime = this.timeCursor.selectedTime; + } + this.timeCursor = new htrace.TimeCursor({ + manager: this.widgetManager, + selectedTime: selectedTime, + el: "#selectedTime" + }); + this.timeCursor.ctx = this.ctx; + this.timeCursor.x0 = this.xD; + this.timeCursor.xF = this.xS; + this.timeCursor.y0 = 0; + this.timeCursor.yF = this.maxY; + this.timeCursor.begin = this.begin; + this.timeCursor.end = this.end; + }, + + draw: function() { + if (this.checkCanvasTooSmall()) { + return; + } + + // Set the background to white. + this.ctx.save(); + this.ctx.fillStyle="#ffffff"; + this.ctx.strokeStyle="#000000"; + this.ctx.fillRect(0, 0, this.maxX, this.maxY); + this.ctx.restore(); + + // Draw all the widgets. + this.widgetManager.handle({type: "draw"}); + }, + + checkCanvasTooSmall: function() { + if ((this.maxX < 200) || (this.maxY < 200)) { + this.ctx.fillStyle="#cccccc"; + this.ctx.strokeStyle="#000000"; + this.ctx.fillRect(0, 0, this.maxX, this.maxY); + this.ctx.font = "24px serif"; + this.ctx.fillStyle="#000000"; + this.ctx.fillText("Canvas too small!", 0, 24); + return true; + } + return false; + }, + + attachEvents: function() { + // Use jquery to capture mouse events on the canvas. + // For some reason using backbone doesn't work for getting these events. + var view = this; + $("#resultsCanvas").off("mousedown"); + $("#resultsCanvas").on("mousedown", function(e) { + view.handleMouseDown(e); + }); + $("#resultsCanvas").off("mouseup"); + $("#resultsCanvas").on("mouseup", function(e) { + view.handleMouseUp(e); + }); + $("#resultsCanvas").off("mouseout"); + $("#resultsCanvas").on("mouseout", function(e) { + view.handleMouseOut(e); + }); + $("#resultsCanvas").off("mousemove"); + $("#resultsCanvas").on("mousemove", function(e) { + view.handleMouseMove(e); + }); + }, + + remove: function() { + $(window).off("resize"); + $("#resultsCanvas").off("mousedown"); + $("#resultsCanvas").off("mouseup"); + $("#resultsCanvas").off("mousemove"); + Backbone.View.prototype.remove.apply(this, arguments); + }, + + handleBeginOrEndChange: function(e, type) { + e.preventDefault(); + var text = $(e.target).val().trim(); + var d = null; + try { + d = htrace.parseDate(text); + } catch(err) { + $("#begin").val(htrace.dateToString(this.begin)); + $("#end").val(htrace.dateToString(this.end)); + htrace.showModalWarning("Timeline " + type + " Format Error", + "Please enter a valid time in the timeline " + type + " field.<p/>" + + err); + return null; + } + if (type === "begin") { + this.setBegin(d.valueOf()); + } else if (type === "end") { + this.setEnd(d.valueOf()); + } else { + throw "invalid type for handleBeginOrEndChange: expected begin or end."; + } + }, + + setBegin: function(val) { + if (this.end < val + this.MINIMUM_TIME_SPAN) { + this.begin = val; + this.end = val + this.MINIMUM_TIME_SPAN; + console.log("SearchResultsView#setBegin(begin=" + this.begin + + ", end=" + this.end + ")"); + $("#begin").val(htrace.dateToString(this.begin)); + $("#end").val(htrace.dateToString(this.end)); + } else { + this.begin = val; + console.log("SearchResultsView#setBegin(begin=" + this.begin + ")"); + $("#begin").val(htrace.dateToString(this.begin)); + } + this.render(); + }, + + setEnd: function(val) { + if (this.begin + this.MINIMUM_TIME_SPAN > val) { + this.begin = val; + this.end = this.begin + this.MINIMUM_TIME_SPAN; + console.log("SearchResultsView#setEnd(begin=" + this.begin + + ", end=" + this.end + ")"); + $("#begin").val(htrace.dateToString(this.begin)); + $("#end").val(htrace.dateToString(this.end)); + } else { + this.end = val; + console.log("SearchResultsView#setEnd(end=" + this.end + ")"); + $("#end").val(htrace.dateToString(this.end)); + } + this.render(); + }, + + zoomFitAll: function() { + var numResults = this.searchResults.size(); + if (numResults == 0) { + this.setBegin(0); + this.setEnd(this.MINIMUM_TIME_SPAN); + return; + } + var minStart = 4503599627370496; + var maxEnd = 0; + for (var i = 0; i < numResults; i++) { + var span = this.searchResults.at(i); + var begin = span.getEarliestBegin(); + if (begin < minStart) { + minStart = begin; + } + var end = span.getLatestEnd(); + if (end > minStart) { + maxEnd = end; + } + } + this.setBegin(minStart); + this.setEnd(maxEnd); + }, + + // Apply a function to all spans + applyToAllSpans: function(cb) { + for (var i = 0; i < this.searchResults.length; i++) { + htrace.treeTraverseDepthFirstPre(this.searchResults.at(i), + htrace.getReifiedChildren, 0, + function(node, depth) { + console.log("node = " + node + ", node.constructor.name = " + node.constructor.name); + cb(node); + }); + htrace.treeTraverseDepthFirstPre(this.searchResults.at(i), + htrace.getReifiedParents, 0, + function(node, depth) { + if (depth > 0) { + cb(node); + } + }); + } + } +});
