text:
<spinner name="spinnerNew" ng-cloak="">

Please Wait...

</spinner>

                    User Dashboard
                    Control panel

Home

Super User Options

System Users

                                                Type User
                                                Module Business Admin
                                                Module User Admin
                                                Module Device Admin
                                                Module Route Admin
                                                Module Stops Admin
                                                Module Super Options

                                                Administrator
                                                <input type="checkbox" name="n_admin_1" ng-model="checkBoxAdmin.object[0].checkBoxActive"/>
                                                <input type="checkbox" name="n_admin_2" ng-model="checkBoxAdmin.object[1].checkBoxActive"/>
                                                <input type="checkbox" name="n_admin_3" ng-model="checkBoxAdmin.object[2].checkBoxActive"/>
                                                <input type="checkbox" name="n_admin_4" ng-model="checkBoxAdmin.object[3].checkBoxActive"/>
                                                <input type="checkbox" name="n_admin_5" ng-model="checkBoxAdmin.object[4].checkBoxActive"/>
                                                <input type="checkbox" name="n_admin_6" ng-model="checkBoxAdmin.object[5].checkBoxActive"/>

                                                Call center
                                                <input type="checkbox" name="n_call_1" ng-model="checkBoxCallCenter.object[0].checkBoxActive"/>
                                                <input type="checkbox" name="n_call_2" ng-model="checkBoxCallCenter.object[1].checkBoxActive"/>
                                                <input type="checkbox" name="n_call_3" ng-model="checkBoxCallCenter.object[2].checkBoxActive"/>
                                                <input type="checkbox" name="n_call_4" ng-model="checkBoxCallCenter.object[3].checkBoxActive"/>
                                                <input type="checkbox" name="n_call_5" ng-model="checkBoxCallCenter.object[4].checkBoxActive"/>
                                                <input type="checkbox" name="n_call_6" ng-model="checkBoxCallCenter.object[5].checkBoxActive"/>

                                                School
                                                <input type="checkbox" name="n_school_1" ng-model="checkBoxSchool.object[0].checkBoxActive"/>
                                                <input type="checkbox" name="n_school_2" ng-model="checkBoxSchool.object[1].checkBoxActive"/>
                                                <input type="checkbox" name="n_school_3" ng-model="checkBoxSchool.object[2].checkBoxActive"/>
                                                <input type="checkbox" name="n_school_4" ng-model="checkBoxSchool.object[3].checkBoxActive"/>
                                                <input type="checkbox" name="n_school_5" ng-model="checkBoxSchool.object[4].checkBoxActive"/>
                                                <input type="checkbox" name="n_school_6" ng-model="checkBoxSchool.object[5].checkBoxActive"/>

                                    <button class="btn btn-block btn-primary btn-md "
                                            ng-click="saveAccess()">Save
                                    </button>


text:
namespace gfx {
class Display;
}

namespace ui {
class CursorLoader;
}

namespace ash {

// A utility class that provides cursors for NativeCursors for which we have
// image resources.
class ASH_EXPORT ImageCursors {
 public:
  ImageCursors();
  ~ImageCursors();

  // Returns the display the cursors are loaded for. The display must
  // be set by SetDisplay before using this.
  gfx::Display GetDisplay() const;

  // Sets the display the cursors are loaded for. The device scale factor
  // determines the size of the image to load, and the rotation of the display
  // determines if the image and its host point has to be retated.
  // Returns true if the cursor image is reloaded.
  bool SetDisplay(const gfx::Display& display);

  // Sets the scale of the mouse cursor icon.
  void SetScale(float scale);

  // Sets the platform cursor based on the native type of |cursor|.
  void SetPlatformCursor(gfx::NativeCursor* cursor);

  // Sets the cursor resource module name for non system cursors.
  void SetCursorResourceModule(const base::string16& module_name);

 private:
  // Reloads the all loaded cursors in the cursor loader.
  void ReloadCursors();

  scoped_ptr<ui::CursorLoader> cursor_loader_;
  float scale_;

  DISALLOW_COPY_AND_ASSIGN(ImageCursors);
};

}  // namespace ash

#endif  // ASH_WM_IMAGE_CURSORS_H_

redpajama_set_name: RedPajamaGithub


text:
package com.dslplatform.json;

import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.math.BigDecimal;

public class LimitsTest {

	@Test
	public void numberLimit() throws IOException {
		DslJson<Object> json = new DslJson<Object>(new DslJson.Settings<Object>().limitDigitsBuffer(20));
		byte[] input = "123456789012345678901234567890".getBytes("UTF-8");
		try {
			json.deserialize(BigDecimal.class, input, input.length);
			Assert.fail("Expecting exception");
		} catch (ParsingException ex) {
			Assert.assertEquals("Too many digits detected in number: '30' at position: 0, before: `12345678901234567890`", ex.getMessage());
		}
	}

	@Test
	public void numberLimitMinInfo() throws IOException {
		DslJson<Object> json = new DslJson<Object>(new DslJson.Settings<Object>().limitDigitsBuffer(20).errorInfo(JsonReader.ErrorInfo.MINIMAL));
		byte[] input = "123456789012345678901234567890".getBytes("UTF-8");
		try {
			json.deserialize(BigDecimal.class, input, input.length);
			Assert.fail("Expecting exception");
		} catch (ParsingException ex) {
			Assert.assertEquals("Too many digits detected in number", ex.getMessage());
		}
	}

	@Test
	public void stringLimit() throws IOException {
		DslJson<Object> json = new DslJson<Object>(new DslJson.Settings<Object>().limitStringBuffer(70));
		byte[] input = "\"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\"".getBytes("UTF-8");
		try {
			json.deserialize(String.class, input, input.length);
			Assert.fail("Expecting exception");
		} catch (ParsingException ex) {
			Assert.assertEquals("Maximum string buffer limit exceeded: '70' at position: 1, following: `\"`, before: `01234567890123456789`", ex.getMessage());
		}
	}
}


text:
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';

import { GrowlerComponent } from './growler.component';
import { GrowlerService } from './growler.service';
import { EnsureModuleLoadedOnceGuard } from '../ensure-module-loaded-once.guard';

@NgModule({
  imports: [CommonModule],
  exports: [GrowlerComponent],
  providers: [GrowlerService],
  declarations: [GrowlerComponent]
})
export class GrowlerModule extends EnsureModuleLoadedOnceGuard {    // Ensure that GrowlerModule is only loaded into AppModule

  // Looks for the module in the parent injector to see if it's already been loaded (only want it loaded once)
  constructor(@Optional() @SkipSelf() parentModule: GrowlerModule) {
    super(parentModule);
  }
}


text:
import type { IClickEvent } from "./IClickEvent";
import type { IHoverEvent } from "./IHoverEvent";
import type { IDivEvent } from "./IDivEvent";
import type { IOptionLoader } from "../../IOptionLoader";
import { SingleOrMultiple } from "../../../../Types/SingleOrMultiple";
export interface IEvents extends IOptionLoader<IEvents> {
    onclick: IClickEvent;
    onhover: IHoverEvent;
    ondiv: SingleOrMultiple<IDivEvent>;
    onClick: IClickEvent;
    onHover: IHoverEvent;
    onDiv: SingleOrMultiple<IDivEvent>;
    resize: boolean;
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<!-- default namespace for elements: cgn -->
<root xmlns="https://github.com/fourier/cgn"
      xmlns:cgn="https://github.com/fourier/cgn"
      xmlns:jcgn="https://github.com/fourier/cgn/java">

  <!-- this test tests the 3rd transformation phase -->

  <cgn:copyright>
    Copyright (c) 2014 by My Company
    This file and its contents are Confidential.
  </cgn:copyright>

  <cgn:author>John Doe</cgn:author>

  <!-- test if the :
       cgn:copyright
       cgn:author
       cgn:package
       cgn:read-only
       cgn:json
       cgn:is-set
       are not specified in cgn:object, take them from parent cgn:objects
  -->
  <objects cgn:package="com.test.phase3.object.attributes.from.parent"
           cgn:read-only="false"
           cgn:json="true"
           cgn:is-set="true">
    <object cgn:name="Test1"/>
  </objects>

  <!-- use own :
       cgn:copyright
       cgn:author
       cgn:package
       cgn:read-only
       cgn:json
       cgn:is-set
       attributes specified in cgn:object instead of parent cgn:objects
  -->
  <objects cgn:package="com.arrays.test"
           cgn:json="false">
    <object cgn:name="Test2"
            cgn:copyright="Some cool company"
            cgn:author="Another Author"
            cgn:package="com.test.phase3.object.attributes.own"
            cgn:read-only="true"
            cgn:json="yes"
            cgn:is-set="yes">
      <field cgn:name="some-field"/>
    </object>
  </objects>

</root>


text:
#pragma once
#include <aws/ec2/EC2_EXPORTS.h>
#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
#include <aws/core/utils/memory/stl/AWSString.h>
#include <utility>

namespace Aws
{
namespace Utils
{
namespace Xml
{
  class XmlNode;
} // namespace Xml
} // namespace Utils
namespace EC2
{
namespace Model
{

  /**
   *
Describes a license configuration.

See Also:
   AWS
   * API Reference

   */
  class AWS_EC2_API LicenseConfiguration
  {
  public:
    LicenseConfiguration();
    LicenseConfiguration(const Aws::Utils::Xml::XmlNode& xmlNode);
    LicenseConfiguration& operator=(const Aws::Utils::Xml::XmlNode& xmlNode);

    void OutputToStream(Aws::OStream& ostream, const char* location, unsigned index, const char* locationValue) const;
    void OutputToStream(Aws::OStream& oStream, const char* location) const;

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline const Aws::String& GetLicenseConfigurationArn() const{ return m_licenseConfigurationArn; }

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline bool LicenseConfigurationArnHasBeenSet() const { return m_licenseConfigurationArnHasBeenSet; }

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline void SetLicenseConfigurationArn(const Aws::String& value) { m_licenseConfigurationArnHasBeenSet = true; m_licenseConfigurationArn = value; }

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline void SetLicenseConfigurationArn(Aws::String&& value) { m_licenseConfigurationArnHasBeenSet = true; m_licenseConfigurationArn = std::move(value); }

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline void SetLicenseConfigurationArn(const char* value) { m_licenseConfigurationArnHasBeenSet = true; m_licenseConfigurationArn.assign(value); }

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline LicenseConfiguration& WithLicenseConfigurationArn(const Aws::String& value) { SetLicenseConfigurationArn(value); return *this;}

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline LicenseConfiguration& WithLicenseConfigurationArn(Aws::String&& value) { SetLicenseConfigurationArn(std::move(value)); return *this;}

    /**
     *
The Amazon Resource Name (ARN) of the license configuration.

     */
    inline LicenseConfiguration& WithLicenseConfigurationArn(const char* value) { SetLicenseConfigurationArn(value); return *this;}

  private:

    Aws::String m_licenseConfigurationArn;
    bool m_licenseConfigurationArnHasBeenSet = false;
  };

} // namespace Model
} // namespace EC2
} // namespace Aws


text:
@class LJWKeyboardToolBar;
@protocol LJWKeyboardToolBarDelegate <NSObject>

@optional;
- (void)ljwKeyboardToolBar:(LJWKeyboardToolBar *)toolBar didClickLastItem:(UIBarButtonItem *)item;

- (void)ljwKeyboardToolBar:(LJWKeyboardToolBar *)toolBar didClickNextItem:(UIBarButtonItem *)item;

- (void)ljwKeyboardToolBar:(LJWKeyboardToolBar *)toolBar didClickDoneItem:(UIBarButtonItem *)item;

@end

@interface LJWKeyboardToolBar : UIToolbar

@property (nonatomic, weak) id<LJWKeyboardToolBarDelegate> ljwKeyboardDelegate;

@property (nonatomic, strong) NSMutableArray *responders;

@property (nonatomic, strong) UIResponder *currentResponder;

@property (nonatomic, assign) NSInteger currentResponderIndex;

@end


text:
[![Gem Version](https://badge.fury.io/rb/try_api.svg)](https://badge.fury.io/rb/try_api)
[![Code Climate](https://codeclimate.com/github/mskubenich/try_api/badges/gpa.svg)](https://codeclimate.com/github/mskubenich/try_api)
[![Issue Count](https://codeclimate.com/github/mskubenich/try_api/badges/issue_count.svg)](https://codeclimate.com/github/mskubenich/try_api)

Simple autogenerated live API documentation for Rails applications.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'try_api'
```

And then execute:

    $ bundle

This will generate config file example:

    $ rails generate try_api:install

Mount try_api engine to your routes. Add this to routes.rb

```ruby
mount TryApi::Engine => '/developers'
```

## Usage

Modify [config/try_api/base.yml](lib/generators/try_api/templates/try_api/base.yml)

## Contributing

Bug reports and pull requests are welcome:

1. Fork it
2. Create your feature branch(git checkout -b my-new-feature)
3. Commit your changes(git commit -am 'Add some feature')
4. Push to the branch(git push origin my-new-feature)
5. Create new Pull Request

## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).


text:
<!---
# 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.
-->
# Apache Hadoop  0.21.1 Release Notes

These release notes cover new developer and user-facing incompatibilities, important issues, features, and major improvements.

---

* [MAPREDUCE-2032](https://issues.apache.org/jira/browse/MAPREDUCE-2032) | *Major* | **TestJobOutputCommitter fails in ant test run**

Clears a problem that {{TestJobCleanup}} leaves behind files that cause {{TestJobOutputCommitter}} to error out.

---

* [HADOOP-6971](https://issues.apache.org/jira/browse/HADOOP-6971) | *Major* | **Clover build doesn't generate per-test coverage**

This fix requires that test coverage is running under Clover 3.0+

---

* [HDFS-1420](https://issues.apache.org/jira/browse/HDFS-1420) | *Major* | **Clover build doesn't generate per-test coverage**

This fix requires that test coverage is running under Clover 3.0+

---

* [MAPREDUCE-2090](https://issues.apache.org/jira/browse/MAPREDUCE-2090) | *Major* | **Clover build doesn't generate per-test coverage**

This fix requires that test coverage is running under Clover 3.0+

---

* [MAPREDUCE-2040](https://issues.apache.org/jira/browse/MAPREDUCE-2040) | *Minor* | **Forrest Documentation for Dynamic Priority Scheduler**

Forrest Documentation for Dynamic Priority Scheduler

---

* [HADOOP-6944](https://issues.apache.org/jira/browse/HADOOP-6944) | *Major* | **[Herriot] Implement a functionality for getting proxy users definitions like groups and hosts.**

I have just committed this to 0.21 and trunk. Thanks Vinay.

---

* [MAPREDUCE-1905](https://issues.apache.org/jira/browse/MAPREDUCE-1905) | *Blocker* | **Context.setStatus() and progress() api are ignored**

Moved the api public Counter getCounter(Enum\<?\> counterName), public Counter getCounter(String groupName, String counterName) from org.apache.hadoop.mapreduce.TaskInputOutputContext to org.apache.hadoop.mapreduce.TaskAttemptContext

---

* [HDFS-1596](https://issues.apache.org/jira/browse/HDFS-1596) | *Major* | **Move secondary namenode checkpoint configs from core-default.xml to hdfs-default.xml**

Removed references to the older fs.checkpoint.\* properties that resided in core-site.xml

---

* [HADOOP-7117](https://issues.apache.org/jira/browse/HADOOP-7117) | *Major* | **Move secondary namenode checkpoint configs from core-default.xml to hdfs-default.xml**

Removed references to the older fs.checkpoint.\* properties that resided in core-site.xml

---

* [HADOOP-7193](https://issues.apache.org/jira/browse/HADOOP-7193) | *Minor* | **Help message is wrong for touchz command.**

Updated the help for the touchz command.


text:
define([ ], function() {

    var exports = { };

    //     Underscore.js 1.5.2
    //     http://underscorejs.org
    //     (c) 2009-2013 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._;

        // Establish the object that gets returned to break out of a loop iteration.
        var breaker = {};

        // 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
            nativeForEach      = ArrayProto.forEach,
            nativeMap          = ArrayProto.map,
            nativeReduce       = ArrayProto.reduce,
            nativeReduceRight  = ArrayProto.reduceRight,
            nativeFilter       = ArrayProto.filter,
            nativeEvery        = ArrayProto.every,
            nativeSome         = ArrayProto.some,
            nativeIndexOf      = ArrayProto.indexOf,
            nativeLastIndexOf  = ArrayProto.lastIndexOf,
            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 via a string identifier,
        // for Closure Compiler "advanced" mode.
        if (typeof exports !== 'undefined') {
            if (typeof module !== 'undefined' && module.exports) {
                exports = module.exports = _;
            }
            exports._ = _;
        } else {
            root._ = _;
        }

        // Current version.
        _.VERSION = '1.5.2';

        // Collection Functions
        // --------------------

        // The cornerstone, an `each` implementation, aka `forEach`.
        // Handles objects with the built-in `forEach`, arrays, and raw objects.
        // Delegates to **ECMAScript 5**'s native `forEach` if available.
        var each = _.each = _.forEach = function(obj, iterator, context) {
            if (obj == null) return;
            if (nativeForEach && obj.forEach === nativeForEach) {
                obj.forEach(iterator, context);
            } else if (obj.length === +obj.length) {
                for (var i = 0, length = obj.length; i < length; i++) {
                    if (iterator.call(context, obj[i], i, obj) === breaker) return;
                }
            } else {
                var keys = _.keys(obj);
                for (var i = 0, length = keys.length; i < length; i++) {
                    if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
                }
            }
        };

        // Return the results of applying the iterator to each element.
        // Delegates to **ECMAScript 5**'s native `map` if available.
        _.map = _.collect = function(obj, iterator, context) {
            var results = [];
            if (obj == null) return results;
            if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
            each(obj, function(value, index, list) {
                results.push(iterator.call(context, value, index, list));
            });
            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`. Delegates to **ECMAScript 5**'s native `reduce` if available.
        _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
            var initial = arguments.length > 2;
            if (obj == null) obj = [];
            if (nativeReduce && obj.reduce === nativeReduce) {
                if (context) iterator = _.bind(iterator, context);
                return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
            }
            each(obj, function(value, index, list) {
                if (!initial) {
                    memo = value;
                    initial = true;
                } else {
                    memo = iterator.call(context, memo, value, index, list);
                }
            });
            if (!initial) throw new TypeError(reduceError);
            return memo;
        };

        // The right-associative version of reduce, also known as `foldr`.
        // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
        _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
            var initial = arguments.length > 2;
            if (obj == null) obj = [];
            if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
                if (context) iterator = _.bind(iterator, context);
                return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
            }
            var length = obj.length;
            if (length !== +length) {
                var keys = _.keys(obj);
                length = keys.length;
            }
            each(obj, function(value, index, list) {
                index = keys ? keys[--length] : --length;
                if (!initial) {
                    memo = obj[index];
                    initial = true;
                } else {
                    memo = iterator.call(context, memo, obj[index], index, list);
                }
            });
            if (!initial) throw new TypeError(reduceError);
            return memo;
        };

        // Return the first value which passes a truth test. Aliased as `detect`.
        _.find = _.detect = function(obj, iterator, context) {
            var result;
            any(obj, function(value, index, list) {
                if (iterator.call(context, value, index, list)) {
                    result = value;
                    return true;
                }
            });
            return result;
        };

        // Return all the elements that pass a truth test.
        // Delegates to **ECMAScript 5**'s native `filter` if available.
        // Aliased as `select`.
        _.filter = _.select = function(obj, iterator, context) {
            var results = [];
            if (obj == null) return results;
            if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
            each(obj, function(value, index, list) {
                if (iterator.call(context, value, index, list)) results.push(value);
            });
            return results;
        };

        // Return all the elements for which a truth test fails.
        _.reject = function(obj, iterator, context) {
            return _.filter(obj, function(value, index, list) {
                return !iterator.call(context, value, index, list);
            }, context);
        };

        // Determine whether all of the elements match a truth test.
        // Delegates to **ECMAScript 5**'s native `every` if available.
        // Aliased as `all`.
        _.every = _.all = function(obj, iterator, context) {
            iterator || (iterator = _.identity);
            var result = true;
            if (obj == null) return result;
            if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
            each(obj, function(value, index, list) {
                if (!(result = result && iterator.call(context, value, index, list))) return breaker;
            });
            return !!result;
        };

        // Determine if at least one element in the object matches a truth test.
        // Delegates to **ECMAScript 5**'s native `some` if available.
        // Aliased as `any`.
        var any = _.some = _.any = function(obj, iterator, context) {
            iterator || (iterator = _.identity);
            var result = false;
            if (obj == null) return result;
            if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
            each(obj, function(value, index, list) {
                if (result || (result = iterator.call(context, value, index, list))) return breaker;
            });
            return !!result;
        };

        // 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 (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
            return any(obj, function(value) {
                return value === target;
            });
        };

        // 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, function(value){ return value[key]; });
        };

        // Convenience version of a common use case of `filter`: selecting only objects
        // containing specific `key:value` pairs.
        _.where = function(obj, attrs, first) {
            if (_.isEmpty(attrs)) return first ? void 0 : [];
            return _[first ? 'find' : 'filter'](obj, function(value) {
                for (var key in attrs) {
                    if (attrs[key] !== value[key]) return false;
                }
                return true;
            });
        };

        // Convenience version of a common use case of `find`: getting the first object
        // containing specific `key:value` pairs.
        _.findWhere = function(obj, attrs) {
            return _.where(obj, attrs, true);
        };

        // Return the maximum element or (element-based computation).
        // Can't optimize arrays of integers longer than 65,535 elements.
        // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
        _.max = function(obj, iterator, context) {
            if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
                return Math.max.apply(Math, obj);
            }
            if (!iterator && _.isEmpty(obj)) return -Infinity;
            var result = {computed : -Infinity, value: -Infinity};
            each(obj, function(value, index, list) {
                var computed = iterator ? iterator.call(context, value, index, list) : value;
                computed > result.computed && (result = {value : value, computed : computed});
            });
            return result.value;
        };

        // Return the minimum element (or element-based computation).
        _.min = function(obj, iterator, context) {
            if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
                return Math.min.apply(Math, obj);
            }
            if (!iterator && _.isEmpty(obj)) return Infinity;
            var result = {computed : Infinity, value: Infinity};
            each(obj, function(value, index, list) {
                var computed = iterator ? iterator.call(context, value, index, list) : value;
                computed < result.computed && (result = {value : value, computed : computed});
            });
            return result.value;
        };

        // Shuffle an array, using the modern version of the
        // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
        _.shuffle = function(obj) {
            var rand;
            var index = 0;
            var shuffled = [];
            each(obj, function(value) {
                rand = _.random(index++);
                shuffled[index - 1] = shuffled[rand];
                shuffled[rand] = value;
            });
            return shuffled;
        };

        // Sample **n** random values from an array.
        // If **n** is not specified, returns a single random element from the array.
        // The internal `guard` argument allows it to work with `map`.
        _.sample = function(obj, n, guard) {
            if (arguments.length < 2 || guard) {
                return obj[_.random(obj.length - 1)];
            }
            return _.shuffle(obj).slice(0, Math.max(0, n));
        };

        // An internal function to generate lookup iterators.
        var lookupIterator = function(value) {
            return _.isFunction(value) ? value : function(obj){ return obj[value]; };
        };

        // Sort the object's values by a criterion produced by an iterator.
        _.sortBy = function(obj, value, context) {
            var iterator = lookupIterator(value);
            return _.pluck(_.map(obj, function(value, index, list) {
                return {
                    value: value,
                    index: index,
                    criteria: iterator.call(context, 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, value, context) {
                var result = {};
                var iterator = value == null ? _.identity : lookupIterator(value);
                each(obj, function(value, index) {
                    var key = iterator.call(context, value, index, obj);
                    behavior(result, key, value);
                });
                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, key, value) {
            (_.has(result, key) ? result[key] : (result[key] = [])).push(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, key, value) {
            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, key) {
            _.has(result, key) ? result[key]++ : 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, iterator, context) {
            iterator = iterator == null ? _.identity : lookupIterator(iterator);
            var value = iterator.call(context, obj);
            var low = 0, high = array.length;
            while (low < high) {
                var mid = (low + high) >>> 1;
                iterator.call(context, array[mid]) < value ? low = mid + 1 : 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;
        };

        // 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;
            return (n == null) || guard ? array[0] : 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, 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];
            } else {
                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, output) {
            if (shallow && _.every(input, _.isArray)) {
                return concat.apply(output, input);
            }
            each(input, function(value) {
                if (_.isArray(value) || _.isArguments(value)) {
                    shallow ? push.apply(output, value) : flatten(value, shallow, output);
                } else {
                    output.push(value);
                }
            });
            return output;
        };

        // Flatten out an array, either recursively (by default), or just one level.
        _.flatten = function(array, shallow) {
            return flatten(array, shallow, []);
        };

        // 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, iterator, context) {
            if (_.isFunction(isSorted)) {
                context = iterator;
                iterator = isSorted;
                isSorted = false;
            }
            var initial = iterator ? _.map(array, iterator, context) : array;
            var results = [];
            var seen = [];
            each(initial, function(value, index) {
                if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
                    seen.push(value);
                    results.push(array[index]);
                }
            });
            return results;
        };

        // Produce an array that contains the union: each distinct element from all of
        // the passed-in arrays.
        _.union = function() {
            return _.uniq(_.flatten(arguments, true));
        };

        // Produce an array that contains every item shared between all the
        // passed-in arrays.
        _.intersection = function(array) {
            var rest = slice.call(arguments, 1);
            return _.filter(_.uniq(array), function(item) {
                return _.every(rest, function(other) {
                    return _.indexOf(other, item) >= 0;
                });
            });
        };

        // 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 = concat.apply(ArrayProto, slice.call(arguments, 1));
            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() {
            var length = _.max(_.pluck(arguments, "length").concat(0));
            var results = new 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;
        };

        // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
        // we need this function. Return the position of the first occurrence of an
        // item in an array, or -1 if the item is not included in the array.
        // Delegates to **ECMAScript 5**'s native `indexOf` if available.
        // 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;
                }
            }
            if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
            for (; i < length; i++) if (array[i] === item) return i;
            return -1;
        };

        // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
        _.lastIndexOf = function(array, item, from) {
            if (array == null) return -1;
            var hasIndex = from != null;
            if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
                return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
            }
            var i = (hasIndex ? from : array.length);
            while (i--) if (array[i] === item) return i;
            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 = arguments[2] || 1;

            var length = Math.max(Math.ceil((stop - start) / step), 0);
            var idx = 0;
            var range = new Array(length);

            while(idx < length) {
                range[idx++] = start;
                start += step;
            }

            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;
            args = slice.call(arguments, 2);
            return 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 (Object(result) === result) return result;
                return self;
            };
        };

        // Partially apply a function by creating a version that has had some of its
        // arguments pre-filled, without changing its dynamic `this` context.
        _.partial = function(func) {
            var args = slice.call(arguments, 1);
            return function() {
                return func.apply(this, args.concat(slice.call(arguments)));
            };
        };

        // Bind all of an object's methods to that object. Useful for ensuring that
        // all callbacks defined on an object belong to it.
        _.bindAll = function(obj) {
            var funcs = slice.call(arguments, 1);
            if (funcs.length === 0) throw new Error("bindAll must be passed function names");
            each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
            return obj;
        };

        // Memoize an expensive function by storing its results.
        _.memoize = function(func, hasher) {
            var memo = {};
            hasher || (hasher = _.identity);
            return function() {
                var key = hasher.apply(this, arguments);
                return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
            };
        };

        // 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;
            options || (options = {});
            var later = function() {
                previous = options.leading === false ? 0 : new Date;
                timeout = null;
                result = func.apply(context, args);
            };
            return function() {
                var now = new Date;
                if (!previous && options.leading === false) previous = now;
                var remaining = wait - (now - previous);
                context = this;
                args = arguments;
                if (remaining <= 0) {
                    clearTimeout(timeout);
                    timeout = null;
                    previous = now;
                    result = func.apply(context, args);
                } 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;
            return function() {
                context = this;
                args = arguments;
                timestamp = new Date();
                var later = function() {
                    var last = (new Date()) - timestamp;
                    if (last < wait) {
                        timeout = setTimeout(later, wait - last);
                    } else {
                        timeout = null;
                        if (!immediate) result = func.apply(context, args);
                    }
                };
                var callNow = immediate && !timeout;
                if (!timeout) {
                    timeout = setTimeout(later, wait);
                }
                if (callNow) result = func.apply(context, args);
                return result;
            };
        };

        // Returns a function that will be executed at most one time, no matter how
        // often you call it. Useful for lazy initialization.
        _.once = function(func) {
            var ran = false, memo;
            return function() {
                if (ran) return memo;
                ran = true;
                memo = func.apply(this, arguments);
                func = null;
                return memo;
            };
        };

        // 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 function() {
                var args = [func];
                push.apply(args, arguments);
                return wrapper.apply(this, args);
            };
        };

        // 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 funcs = arguments;
            return function() {
                var args = arguments;
                for (var i = funcs.length - 1; i >= 0; i--) {
                    args = [funcs[i].apply(this, args)];
                }
                return args[0];
            };
        };

        // 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);
                }
            };
        };

        // Object Functions
        // ----------------

        // Retrieve the names of an object's properties.
        // Delegates to **ECMAScript 5**'s native `Object.keys`
        _.keys = nativeKeys || function(obj) {
            if (obj !== Object(obj)) throw new TypeError('Invalid object');
            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 = new 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 = new 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) {
            each(slice.call(arguments, 1), function(source) {
                if (source) {
                    for (var prop in source) {
                        obj[prop] = source[prop];
                    }
                }
            });
            return obj;
        };

        // Return a copy of the object only containing the whitelisted properties.
        _.pick = function(obj) {
            var copy = {};
            var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
            each(keys, function(key) {
                if (key in obj) copy[key] = obj[key];
            });
            return copy;
        };

         // Return a copy of the object without the blacklisted properties.
        _.omit = function(obj) {
            var copy = {};
            var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
            for (var key in obj) {
                if (!_.contains(keys, key)) copy[key] = obj[key];
            }
            return copy;
        };

        // Fill in a given object with default properties.
        _.defaults = function(obj) {
            each(slice.call(arguments, 1), function(source) {
                if (source) {
                    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, dates, and booleans are compared by value.
                case '[object String]':
                    // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
                    // equivalent to `new String("5")`.
                    return a == String(b);
                case '[object Number]':
                    // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
                    // other numeric values.
                    return a != +a ? b != +b : (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;
                // RegExps are compared by their source patterns and flags.
                case '[object RegExp]':
                    return a.source == b.source &&
                                 a.global == b.global &&
                                 a.multiline == b.multiline &&
                                 a.ignoreCase == b.ignoreCase;
            }
            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 && !(_.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 = 0, result = true;
            // 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.
                for (var key in a) {
                    if (_.has(a, key)) {
                        // Count the expected number of properties.
                        size++;
                        // Deep compare each member.
                        if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
                    }
                }
                // Ensure that both objects contain the same number of properties.
                if (result) {
                    for (key in b) {
                        if (_.has(b, key) && !(size--)) break;
                    }
                    result = !size;
                }
            }
            // 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)) 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) {
            return obj === 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 !!(obj && _.has(obj, 'callee'));
            };
        }

        // Optimize `isFunction` if appropriate.
        if (typeof (/./) !== 'function') {
            _.isFunction = function(obj) {
                return typeof obj === 'function';
            };
        }

        // 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 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 iterators.
        _.identity = function(value) {
            return value;
        };

        // Run a function **n** times.
        _.times = function(n, iterator, context) {
            var accum = Array(Math.max(0, n));
            for (var i = 0; i < n; i++) accum[i] = iterator.call(context, 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));
        };

        // List of HTML entities for escaping.
        var entityMap = {
            escape: {
                '&': '&',
                '<': '<',
                '>': '>',
                '"': '"',
                "'": '''
            }
        };
        entityMap.unescape = _.invert(entityMap.escape);

        // Regexes containing the keys and values listed immediately above.
        var entityRegexes = {
            escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
            unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
        };

        // Functions for escaping and unescaping strings to/from HTML interpolation.
        _.each(['escape', 'unescape'], function(method) {
            _[method] = function(string) {
                if (string == null) return '';
                return ('' + string).replace(entityRegexes[method], function(match) {
                    return entityMap[method][match];
                });
            };
        });

        // 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) ? value.call(object) : value;
        };

        // 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));
                };
            });
        };

        // 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',
            '\t':     't',
            '\u2028': 'u2028',
            '\u2029': 'u2029'
        };

        var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;

        // JavaScript micro-templating, similar to John Resig's implementation.
        // Underscore templating handles arbitrary delimiters, preserves whitespace,
        // and correctly escapes quotes within interpolated code.
        _.template = function(text, data, settings) {
            var render;
            settings = _.defaults({}, settings, _.templateSettings);

            // Combine delimiters into one regular expression via alternation.
            var matcher = new 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, function(match) { return '\\' + escapes[match]; });

                if (escape) {
                    source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
                }
                if (interpolate) {
                    source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
                }
                if (evaluate) {
                    source += "';\n" + evaluate + "\n__p+='";
                }
                index = offset + match.length;
                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 {
                render = new Function(settings.variable || 'obj', '_', source);
            } catch (e) {
                e.source = source;
                throw e;
            }

            if (data) return render(data, _);
            var template = function(data) {
                return render.call(this, data, _);
            };

            // Provide the compiled function source as a convenience for precompilation.
            template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';

            return template;
        };

        // Add a "chain" function, which will delegate to the wrapper.
        _.chain = function(obj) {
            return _(obj).chain();
        };

        // 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 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));
            };
        });

        _.extend(_.prototype, {

            // Start chaining a wrapped Underscore object.
            chain: function() {
                this._chain = true;
                return this;
            },

            // Extracts the result from a wrapped and chained object.
            value: function() {
                return this._wrapped;
            }

        });

    }).call(exports);

    //  Underscore.string
    //  (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>
    //  Underscore.string is freely distributable under the terms of the MIT license.
    //  Documentation: https://github.com/epeli/underscore.string
    //  Some code is borrowed from MooTools and Alexandru Marasteanu.
    //  Version '2.3.2'

    (function(root, String){
        'use strict';

        // Defining helper functions.

        var nativeTrim = String.prototype.trim;
        var nativeTrimRight = String.prototype.trimRight;
        var nativeTrimLeft = String.prototype.trimLeft;

        var parseNumber = function(source) { return source * 1 || 0; };

        var strRepeat = function(str, qty){
            if (qty < 1) return '';
            var result = '';
            while (qty > 0) {
                if (qty & 1) result += str;
                qty >>= 1, str += str;
            }
            return result;
        };

        var slice = [].slice;

        var defaultToWhiteSpace = function(characters) {
            if (characters == null)
                return '\\s';
            else if (characters.source)
                return characters.source;
            else
                return '[' + _s.escapeRegExp(characters) + ']';
        };

        // Helper for toBoolean
        function boolMatch(s, matchers) {
            var i, matcher, down = s.toLowerCase();
            matchers = [].concat(matchers);
            for (i = 0; i < matchers.length; i += 1) {
                matcher = matchers[i];
                if (!matcher) continue;
                if (matcher.test && matcher.test(s)) return true;
                if (matcher.toLowerCase() === down) return true;
            }
        }

        var escapeChars = {
            lt: '<',
            gt: '>',
            quot: '"',
            amp: '&',
            apos: "'"
        };

        var reversedEscapeChars = {};
        for(var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key;
        reversedEscapeChars["'"] = '#39';

        // sprintf() for JavaScript 0.7-beta1
        // http://www.diveintojavascript.com/projects/javascript-sprintf
        //
        // Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
        // All rights reserved.

        var sprintf = (function() {
            function get_type(variable) {
                return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
            }

            var str_repeat = strRepeat;

            var str_format = function() {
                if (!str_format.cache.hasOwnProperty(arguments[0])) {
                    str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
                }
                return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
            };

            str_format.format = function(parse_tree, argv) {
                var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
                for (i = 0; i < tree_length; i++) {
                    node_type = get_type(parse_tree[i]);
                    if (node_type === 'string') {
                        output.push(parse_tree[i]);
                    }
                    else if (node_type === 'array') {
                        match = parse_tree[i]; // convenience purposes only
                        if (match[2]) { // keyword argument
                            arg = argv[cursor];
                            for (k = 0; k < match[2].length; k++) {
                                if (!arg.hasOwnProperty(match[2][k])) {
                                    throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
                                }
                                arg = arg[match[2][k]];
                            }
                        } else if (match[1]) { // positional argument (explicit)
                            arg = argv[match[1]];
                        }
                        else { // positional argument (implicit)
                            arg = argv[cursor++];
                        }

                        if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
                            throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
                        }
                        switch (match[8]) {
                            case 'b': arg = arg.toString(2); break;
                            case 'c': arg = String.fromCharCode(arg); break;
                            case 'd': arg = parseInt(arg, 10); break;
                            case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
                            case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
                            case 'o': arg = arg.toString(8); break;
                            case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
                            case 'u': arg = Math.abs(arg); break;
                            case 'x': arg = arg.toString(16); break;
                            case 'X': arg = arg.toString(16).toUpperCase(); break;
                        }
                        arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
                        pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
                        pad_length = match[6] - String(arg).length;
                        pad = match[6] ? str_repeat(pad_character, pad_length) : '';
                        output.push(match[5] ? arg + pad : pad + arg);
                    }
                }
                return output.join('');
            };

            str_format.cache = {};

            str_format.parse = function(fmt) {
                var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
                while (_fmt) {
                    if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
                        parse_tree.push(match[0]);
                    }
                    else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
                        parse_tree.push('%');
                    }
                    else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
                        if (match[2]) {
                            arg_names |= 1;
                            var field_list = [], replacement_field = match[2], field_match = [];
                            if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
                                field_list.push(field_match[1]);
                                while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
                                    if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
                                        field_list.push(field_match[1]);
                                    }
                                    else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
                                        field_list.push(field_match[1]);
                                    }
                                    else {
                                        throw new Error('[_.sprintf] huh?');
                                    }
                                }
                            }
                            else {
                                throw new Error('[_.sprintf] huh?');
                            }
                            match[2] = field_list;
                        }
                        else {
                            arg_names |= 2;
                        }
                        if (arg_names === 3) {
                            throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
                        }
                        parse_tree.push(match);
                    }
                    else {
                        throw new Error('[_.sprintf] huh?');
                    }
                    _fmt = _fmt.substring(match[0].length);
                }
                return parse_tree;
            };

            return str_format;
        })();

        // Defining underscore.string

        var _s = {

            VERSION: '2.3.0',

            isBlank: function(str){
                if (str == null) str = '';
                return (/^\s*$/).test(str);
            },

            stripTags: function(str){
                if (str == null) return '';
                return String(str).replace(/<\/?[^>]+>/g, '');
            },

            capitalize : function(str){
                str = str == null ? '' : String(str);
                return str.charAt(0).toUpperCase() + str.slice(1);
            },

            chop: function(str, step){
                if (str == null) return [];
                str = String(str);
                step = ~~step;
                return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];
            },

            clean: function(str){
                return _s.strip(str).replace(/\s+/g, ' ');
            },

            count: function(str, substr){
                if (str == null || substr == null) return 0;

                str = String(str);
                substr = String(substr);

                var count = 0,
                    pos = 0,
                    length = substr.length;

                while (true) {
                    pos = str.indexOf(substr, pos);
                    if (pos === -1) break;
                    count++;
                    pos += length;
                }

                return count;
            },

            chars: function(str) {
                if (str == null) return [];
                return String(str).split('');
            },

            swapCase: function(str) {
                if (str == null) return '';
                return String(str).replace(/\S/g, function(c){
                    return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();
                });
            },

            escapeHTML: function(str) {
                if (str == null) return '';
                return String(str).replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; });
            },

            unescapeHTML: function(str) {
                if (str == null) return '';
                return String(str).replace(/\&([^;]+);/g, function(entity, entityCode){
                    var match;

                    if (entityCode in escapeChars) {
                        return escapeChars[entityCode];
                    } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
                        return String.fromCharCode(parseInt(match[1], 16));
                    } else if (match = entityCode.match(/^#(\d+)$/)) {
                        return String.fromCharCode(~~match[1]);
                    } else {
                        return entity;
                    }
                });
            },

            escapeRegExp: function(str){
                if (str == null) return '';
                return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
            },

            splice: function(str, i, howmany, substr){
                var arr = _s.chars(str);
                arr.splice(~~i, ~~howmany, substr);
                return arr.join('');
            },

            insert: function(str, i, substr){
                return _s.splice(str, i, 0, substr);
            },

            include: function(str, needle){
                if (needle === '') return true;
                if (str == null) return false;
                return String(str).indexOf(needle) !== -1;
            },

            join: function() {
                var args = slice.call(arguments),
                    separator = args.shift();

                if (separator == null) separator = '';

                return args.join(separator);
            },

            lines: function(str) {
                if (str == null) return [];
                return String(str).split("\n");
            },

            reverse: function(str){
                return _s.chars(str).reverse().join('');
            },

            startsWith: function(str, starts){
                if (starts === '') return true;
                if (str == null || starts == null) return false;
                str = String(str); starts = String(starts);
                return str.length >= starts.length && str.slice(0, starts.length) === starts;
            },

            endsWith: function(str, ends){
                if (ends === '') return true;
                if (str == null || ends == null) return false;
                str = String(str); ends = String(ends);
                return str.length >= ends.length && str.slice(str.length - ends.length) === ends;
            },

            succ: function(str){
                if (str == null) return '';
                str = String(str);
                return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length-1) + 1);
            },

            titleize: function(str){
                if (str == null) return '';
                str  = String(str).toLowerCase();
                return str.replace(/(?:^|\s|-)\S/g, function(c){ return c.toUpperCase(); });
            },

            camelize: function(str){
                return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c ? c.toUpperCase() : ""; });
            },

            underscored: function(str){
                return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
            },

            dasherize: function(str){
                return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
            },

            classify: function(str){
                return _s.titleize(String(str).replace(/[\W_]/g, ' ')).replace(/\s/g, '');
            },

            humanize: function(str){
                return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));
            },

            trim: function(str, characters){
                if (str == null) return '';
                if (!characters && nativeTrim) return nativeTrim.call(str);
                characters = defaultToWhiteSpace(characters);
                return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), '');
            },

            ltrim: function(str, characters){
                if (str == null) return '';
                if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
                characters = defaultToWhiteSpace(characters);
                return String(str).replace(new RegExp('^' + characters + '+'), '');
            },

            rtrim: function(str, characters){
                if (str == null) return '';
                if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
                characters = defaultToWhiteSpace(characters);
                return String(str).replace(new RegExp(characters + '+$'), '');
            },

            truncate: function(str, length, truncateStr){
                if (str == null) return '';
                str = String(str); truncateStr = truncateStr || '...';
                length = ~~length;
                return str.length > length ? str.slice(0, length) + truncateStr : str;
            },

            /**
             * _s.prune: a more elegant version of truncate
             * prune extra chars, never leaving a half-chopped word.
             * @author github.com/rwz
             */
            prune: function(str, length, pruneStr){
                if (str == null) return '';

                str = String(str); length = ~~length;
                pruneStr = pruneStr != null ? String(pruneStr) : '...';

                if (str.length <= length) return str;

                var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
                    template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'

                if (template.slice(template.length-2).match(/\w\w/))
                    template = template.replace(/\s*\S+$/, '');
                else
                    template = _s.rtrim(template.slice(0, template.length-1));

                return (template+pruneStr).length > str.length ? str : str.slice(0, template.length)+pruneStr;
            },

            words: function(str, delimiter) {
                if (_s.isBlank(str)) return [];
                return _s.trim(str, delimiter).split(delimiter || /\s+/);
            },

            pad: function(str, length, padStr, type) {
                str = str == null ? '' : String(str);
                length = ~~length;

                var padlen  = 0;

                if (!padStr)
                    padStr = ' ';
                else if (padStr.length > 1)
                    padStr = padStr.charAt(0);

                switch(type) {
                    case 'right':
                        padlen = length - str.length;
                        return str + strRepeat(padStr, padlen);
                    case 'both':
                        padlen = length - str.length;
                        return strRepeat(padStr, Math.ceil(padlen/2)) + str
                                        + strRepeat(padStr, Math.floor(padlen/2));
                    default: // 'left'
                        padlen = length - str.length;
                        return strRepeat(padStr, padlen) + str;
                    }
            },

            lpad: function(str, length, padStr) {
                return _s.pad(str, length, padStr);
            },

            rpad: function(str, length, padStr) {
                return _s.pad(str, length, padStr, 'right');
            },

            lrpad: function(str, length, padStr) {
                return _s.pad(str, length, padStr, 'both');
            },

            sprintf: sprintf,

            vsprintf: function(fmt, argv){
                argv.unshift(fmt);
                return sprintf.apply(null, argv);
            },

            toNumber: function(str, decimals) {
                if (!str) return 0;
                str = _s.trim(str);
                if (!str.match(/^-?\d+(?:\.\d+)?$/)) return NaN;
                return parseNumber(parseNumber(str).toFixed(~~decimals));
            },

            numberFormat : function(number, dec, dsep, tsep) {
                if (isNaN(number) || number == null) return '';

                number = number.toFixed(~~dec);
                tsep = typeof tsep == 'string' ? tsep : ',';

                var parts = number.split('.'), fnums = parts[0],
                    decimals = parts[1] ? (dsep || '.') + parts[1] : '';

                return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
            },

            strRight: function(str, sep){
                if (str == null) return '';
                str = String(str); sep = sep != null ? String(sep) : sep;
                var pos = !sep ? -1 : str.indexOf(sep);
                return ~pos ? str.slice(pos+sep.length, str.length) : str;
            },

            strRightBack: function(str, sep){
                if (str == null) return '';
                str = String(str); sep = sep != null ? String(sep) : sep;
                var pos = !sep ? -1 : str.lastIndexOf(sep);
                return ~pos ? str.slice(pos+sep.length, str.length) : str;
            },

            strLeft: function(str, sep){
                if (str == null) return '';
                str = String(str); sep = sep != null ? String(sep) : sep;
                var pos = !sep ? -1 : str.indexOf(sep);
                return ~pos ? str.slice(0, pos) : str;
            },

            strLeftBack: function(str, sep){
                if (str == null) return '';
                str += ''; sep = sep != null ? ''+sep : sep;
                var pos = str.lastIndexOf(sep);
                return ~pos ? str.slice(0, pos) : str;
            },

            toSentence: function(array, separator, lastSeparator, serial) {
                separator = separator || ', ';
                lastSeparator = lastSeparator || ' and ';
                var a = array.slice(), lastMember = a.pop();

                if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator;

                return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;
            },

            toSentenceSerial: function() {
                var args = slice.call(arguments);
                args[3] = true;
                return _s.toSentence.apply(_s, args);
            },

            slugify: function(str) {
                if (str == null) return '';

                var from  = "ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",
                        to    = "aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",
                        regex = new RegExp(defaultToWhiteSpace(from), 'g');

                str = String(str).toLowerCase().replace(regex, function(c){
                    var index = from.indexOf(c);
                    return to.charAt(index) || '-';
                });

                return _s.dasherize(str.replace(/[^\w\s-]/g, ''));
            },

            surround: function(str, wrapper) {
                return [wrapper, str, wrapper].join('');
            },

            quote: function(str, quoteChar) {
                return _s.surround(str, quoteChar || '"');
            },

            unquote: function(str, quoteChar) {
                quoteChar = quoteChar || '"';
                if (str[0] === quoteChar && str[str.length-1] === quoteChar)
                    return str.slice(1,str.length-1);
                else return str;
            },

            exports: function() {
                var result = {};

                for (var prop in this) {
                    if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue;
                    result[prop] = this[prop];
                }

                return result;
            },

            repeat: function(str, qty, separator){
                if (str == null) return '';

                qty = ~~qty;

                // using faster implementation if separator is not needed;
                if (separator == null) return strRepeat(String(str), qty);

                // this one is about 300x slower in Google Chrome
                for (var repeat = []; qty > 0; repeat[--qty] = str) {}
                return repeat.join(separator);
            },

            naturalCmp: function(str1, str2){
                if (str1 == str2) return 0;
                if (!str1) return -1;
                if (!str2) return 1;

                var cmpRegex = /(\.\d+)|(\d+)|(\D+)/g,
                    tokens1 = String(str1).toLowerCase().match(cmpRegex),
                    tokens2 = String(str2).toLowerCase().match(cmpRegex),
                    count = Math.min(tokens1.length, tokens2.length);

                for(var i = 0; i < count; i++) {
                    var a = tokens1[i], b = tokens2[i];

                    if (a !== b){
                        var num1 = parseInt(a, 10);
                        if (!isNaN(num1)){
                            var num2 = parseInt(b, 10);
                            if (!isNaN(num2) && num1 - num2)
                                return num1 - num2;
                        }
                        return a < b ? -1 : 1;
                    }
                }

                if (tokens1.length === tokens2.length)
                    return tokens1.length - tokens2.length;

                return str1 < str2 ? -1 : 1;
            },

            levenshtein: function(str1, str2) {
                if (str1 == null && str2 == null) return 0;
                if (str1 == null) return String(str2).length;
                if (str2 == null) return String(str1).length;

                str1 = String(str1); str2 = String(str2);

                var current = [], prev, value;

                for (var i = 0; i <= str2.length; i++)
                    for (var j = 0; j <= str1.length; j++) {
                        if (i && j)
                            if (str1.charAt(j - 1) === str2.charAt(i - 1))
                                value = prev;
                            else
                                value = Math.min(current[j], current[j - 1], prev) + 1;
                        else
                            value = i + j;

                        prev = current[j];
                        current[j] = value;
                    }

                return current.pop();
            },

            toBoolean: function(str, trueValues, falseValues) {
                if (typeof str === "number") str = "" + str;
                if (typeof str !== "string") return !!str;
                str = _s.trim(str);
                if (boolMatch(str, trueValues || ["true", "1"])) return true;
                if (boolMatch(str, falseValues || ["false", "0"])) return false;
            }
        };

        // Aliases

        _s.strip    = _s.trim;
        _s.lstrip   = _s.ltrim;
        _s.rstrip   = _s.rtrim;
        _s.center   = _s.lrpad;
        _s.rjust    = _s.lpad;
        _s.ljust    = _s.rpad;
        _s.contains = _s.include;
        _s.q        = _s.quote;
        _s.toBool   = _s.toBoolean;

        // Exporting

        // CommonJS module is defined
        if (typeof exports !== 'undefined') {
            if (typeof module !== 'undefined' && module.exports)
                module.exports = _s;

            exports._s = _s;
        }

        // Register as a named module with AMD.
        if (typeof define === 'function' && define.amd)
            define('underscore.string', [], function(){ return _s; });

        // Integrate with Underscore.js if defined
        // or create our own underscore object.
        root._ = root._ || {};
        root._.string = root._.str = _s;
    })(exports, String);

    (function custom(_) {

        _.mixin(_.str.exports());

        _.mixin({
            restrict: function(obj, keys) {
                var o = { };

                _.each(obj, function(value, key) {
                    if(keys.indexOf(key) !== -1) {
                        o[key] = value;
                    }
                });

                return o;
            }
        });

    })(exports._);

    return exports._;

});