tag-search
Version:
search and list html tags like named anchor links
1,555 lines (1,382 loc) • 439 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var _createClass = (function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ('value' in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
}
}return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
};
})();
var _get = function get(_x, _x2, _x3) {
var _again = true;_function: while (_again) {
var object = _x,
property = _x2,
receiver = _x3;desc = parent = getter = undefined;_again = false;if (object === null) object = Function.prototype;var desc = Object.getOwnPropertyDescriptor(object, property);if (desc === undefined) {
var parent = Object.getPrototypeOf(object);if (parent === null) {
return undefined;
} else {
_x = parent;_x2 = property;_x3 = receiver;_again = true;continue _function;
}
} else if ('value' in desc) {
return desc.value;
} else {
var getter = desc.get;if (getter === undefined) {
return undefined;
}return getter.call(receiver);
}
}
};
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { 'default': obj };
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var _react = window.React;
var _react2 = _interopRequireDefault(_react);
var _reactDom = window.ReactDOM;
var _libTagSearchJs = require('../../lib/tag-search.js');
var _libTagSearchJs2 = _interopRequireDefault(_libTagSearchJs);
var anchorOpts = {
useLocation: false,
nostyles: false,
noclasses: false,
searchBar: 'searchBar',
searchList: 'searchList',
tagSelector: 'a[name]',
wrapperLeftText: 'click for menu',
wrapperRightText: 'click to search',
styles: {
'searchBar': {
'height': '50px',
'width': '100%',
'position': 'fixed',
'bottom': 0,
'right': 0,
'zIndex': 1002,
'padding': 0
},
'input': {
'width': '100%',
'fontSize': '1.4em',
'fontWeight': 'bold',
'color': '#88C9FF',
'backgroundColor': '#30475B',
'border': 'none',
'height': '50px',
'zIndex': 1003
},
'inputDiv': {
'paddingTop': 0,
'paddingRight': 0,
'paddingBottom': 0,
'paddingLeft': 8,
'height': '50px'
},
'searchList': {
'height': '300px',
'margin': '-370px 15px 0 15px',
'border': '1px solid #ccc',
'borderBottom': 'none',
'overflowY': 'auto',
'backgroundColor': '#535A5F',
'padding': '10px 20px',
'display': 'none'
},
'ul': {
'fontSize': '13px',
'listStyle': 'none',
'lineHeight': 1.2,
'margin': '0',
'padding': 0,
'position': 'relative',
'zIndex': 2
},
'li': {
'padding': '5px 5px',
'color': '#CACFD2'
},
'li:a': {
'color': '#EEAE18',
'display': 'block',
'padding': '5px 5px 5px 0'
},
'li:heading': {
'fontSize': '1.25em',
'textTransform': 'uppercase',
'padding': '5px 5px',
'color': '#E8ECEF'
},
'context': {
'color': '#F1F1F4',
'fontSize': '.9em',
'display': 'block',
'marginTop': 0,
'height': 'auto'
},
'wrapper': {
'height': '50px',
'position': 'absolute',
'top': 0,
'right': 0,
'zIndex': 1022,
'padding': 0,
'width': '100%',
'backgroundColor': '#18222A',
'color': '#D0DDEA'
},
'wrapperLeft': {
'float': 'right',
'width': '50%',
'textAlign': 'center',
'height': '50px',
'padding': 0,
'margin': '-13px',
'cursor': 'pointer'
},
'wrapperRight': {
'float': 'left',
'width': '50%',
'textAlign': 'center',
'height': '50px',
'padding': 0,
'margin': '-13px',
'cursor': 'pointer'
}
}
};
var App = (function (_React$Component) {
_inherits(App, _React$Component);
function App() {
_classCallCheck(this, App);
_get(Object.getPrototypeOf(App.prototype), 'constructor', this).call(this);
this.state = {};
}
_createClass(App, [{
key: 'render',
value: function render() {
return _react2['default'].createElement(_libTagSearchJs2['default'], { options: anchorOpts });
}
}]);
return App;
})(_react2['default'].Component);
(0, _reactDom.render)(_react2['default'].createElement(App, null), document.getElementById('anchor-search'));
},{"../../lib/tag-search.js":4}],2:[function(require,module,exports){
/* */
'use strict';
'strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var classes = {
'searchBar': '',
'input': '',
'inputDiv': '',
'searchList': '',
'ul': '',
'li': '',
'li:a': '',
'li:heading': '',
'context': ''
};
exports['default'] = classes;
module.exports = exports['default'];
},{}],3:[function(require,module,exports){
/* */
'use strict';
'strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var styles = {
'searchBar': {
'height': '50px',
'width': '100%',
'position': 'fixed',
'bottom': 0,
'right': 0,
'zIndex': 1002,
'padding': 0
},
'input': {
'width': '100%',
'fontSize': '1.4em',
'fontWeight': 'bold',
'color': '#555',
'backgroundColor': '#f7f7f7',
'border': 'none',
'height': '50px',
'zIndex': 1003
},
'inputDiv': {
'paddingTop': 0,
'paddingRight': 0,
'paddingBottom': 0,
'paddingLeft': 8,
'height': '50px'
},
'searchList': {
'height': '300px',
'margin': '-370px 15px 0 15px',
'border': '1px solid #ccc',
'borderBottom': 'none',
'overflowY': 'auto',
'backgroundColor': '#fbfbfb',
'padding': '10px 20px',
'display': 'none'
},
'ul': {
'fontSize': '13px',
'listStyle': 'none',
'lineHeight': 1.2,
'margin': '0',
'padding': 0,
'position': 'relative',
'zIndex': 2
},
'li': {
'padding': '5px 5px',
'color': '#348dd9'
},
'li:a': {
'color': '#333',
'display': 'block',
'padding': '5px 5px 5px 0'
},
'li:heading': {
'fontSize': '1.25em',
'textTransform': 'uppercase',
'padding': '5px 5px',
'color': '#348dd9'
},
'context': {
'color': '#7a7a7a',
'fontSize': '.9em',
'display': 'block',
'marginTop': 0,
'height': 'auto'
},
'wrapper': {
'height': '50px',
'position': 'absolute',
'top': 0,
'right': 0,
'zIndex': 1022,
'padding': 0,
'width': '100%',
'backgroundColor': '#f7f7f7',
'color': '#7a7a7a'
},
'wrapperLeft': {
'float': 'left',
'width': '50%',
'textAlign': 'center',
'height': '50px',
'padding': 0,
'margin': '-13px',
'cursor': 'pointer'
},
'wrapperRight': {
'float': 'left',
'width': '50%',
'textAlign': 'center',
'height': '50px',
'padding': 0,
'margin': '-13px',
'cursor': 'pointer'
},
'active': {
'backgroundColor': '#c9dbea'
},
'caution': {
'backgroundColor': '#efce9e'
}
};
var defaultStyles = {
'searchBar': {},
'input': {},
'inputDiv': {},
'searchList': {},
'ul': {},
'li': {},
'li:a': {},
'li:heading': {},
'context': {},
'active': {
'backgroundColor': '#c9dbea'
},
'caution': {
'backgroundColor': '#efce9e'
},
'wrapper': {
'height': '50px',
'position': 'absolute',
'top': 0,
'right': 0,
'zIndex': 1022,
'padding': 0,
'width': '100%',
'backgroundColor': '#f7f7f7',
'color': '#7a7a7a'
},
'wrapperLeft': {
'float': 'left',
'width': '50%',
'textAlign': 'center',
'height': '50px',
'padding': 0,
'margin': '-13px',
'cursor': 'pointer'
},
'wrapperRight': {
'float': 'left',
'width': '50%',
'textAlign': 'center',
'height': '50px',
'padding': 0,
'margin': '-13px',
'cursor': 'pointer'
}
};
exports['default'] = styles;
exports.defaultStyles = defaultStyles;
},{}],4:[function(require,module,exports){
/* */
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var _createClass = (function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ('value' in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
}
}return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
};
})();
var _get = function get(_x, _x2, _x3) {
var _again = true;_function: while (_again) {
var object = _x,
property = _x2,
receiver = _x3;desc = parent = getter = undefined;_again = false;if (object === null) object = Function.prototype;var desc = Object.getOwnPropertyDescriptor(object, property);if (desc === undefined) {
var parent = Object.getPrototypeOf(object);if (parent === null) {
return undefined;
} else {
_x = parent;_x2 = property;_x3 = receiver;_again = true;continue _function;
}
} else if ('value' in desc) {
return desc.value;
} else {
var getter = desc.get;if (getter === undefined) {
return undefined;
}return getter.call(receiver);
}
}
};
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { 'default': obj };
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
var _react = window.React;
var _react2 = _interopRequireDefault(_react);
var _jquery = window.$;
var _jquery2 = _interopRequireDefault(_jquery);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _styles = require('./styles');
var _styles2 = _interopRequireDefault(_styles);
var _classes = require('./classes');
var _classes2 = _interopRequireDefault(_classes);
var Tagged = (function (_React$Component) {
_inherits(Tagged, _React$Component);
function Tagged(props) {
_classCallCheck(this, Tagged);
_get(Object.getPrototypeOf(Tagged.prototype), 'constructor', this).call(this);
this.displayName = 'anchorSearch';
this.state = {};
// private vars
this._limiters = false;
this._typingBit = false;
this._menuBit = false;
this._tagCache = [];
this._searchTermCache = '';
var opts = 'object' === _jquery2['default'].type(props.options) ? props.options : {};
// Anchored props
this.state.Anchored = {
searchBar: opts.searchBar || 'searchBar',
placeholder: opts.placeholder || "quick find",
searchList: opts.searchList || 'searchList',
tagSelector: opts.tagSelector || 'a[name]',
contextTextUntilTag: opts.contextTextUntilTag || "a[name]",
nameFromTag: opts.nameFromTag || ["H2", "H3", "H4"],
nameFromNextTag: opts.nameFromNextTag ? true : false,
nameFromTagAttr: opts.nameFromTagAttr || 'name',
nameFromTagSaveChildren: opts.nameFromTagSaveChildren || ':not("em, code")',
useLocation: opts.useLocation ? true : false,
noclasses: opts.noclasses ? true : false,
nostyles: opts.nostyles ? true : false,
forceSearch: opts.forceSearch || 2000,
wrapperLeftText: opts.wrapperLeftText || 'menu',
wrapperRightText: opts.wrapperRightText || 'search'
};
// classes
this.state.Anchored.classes = this.state.Anchored.noclasses ? _classes2['default'] : _lodash2['default'].defaults(opts.classes || {}, _classes2['default']);
// styles
this.state.Anchored.styles = this.state.Anchored.nostyles ? _styles.defaultStyles : _lodash2['default'].defaults(opts.styles || {}, _styles2['default']);
var anchored = _react2['default'].createElement('div', { id: this.state.Anchored.searchBar, style: this.state.Anchored.styles.searchBar, className: this.state.Anchored.classes.searchBar }, _react2['default'].createElement('div', { id: 'TSWrapper', style: this.state.Anchored.styles.wrapper }, _react2['default'].createElement('div', { id: 'TSWrapperLeft', style: this.state.Anchored.styles.wrapperLeft }, _react2['default'].createElement('h4', null, this.state.Anchored.wrapperLeftText)), _react2['default'].createElement('div', { id: 'TSWrapperRight', style: this.state.Anchored.styles.wrapperRight }, _react2['default'].createElement('h4', null, this.state.Anchored.wrapperRightText))), _react2['default'].createElement('div', { className: this.state.Anchored.classes.inputDiv, style: this.state.Anchored.styles.inputDiv }, _react2['default'].createElement('input', { style: this.state.Anchored.styles.input, type: 'text', placeholder: this.state.Anchored.placeholder, className: this.state.Anchored.classes.input }), _react2['default'].createElement('nav', { style: this.state.Anchored.styles.searchList, id: this.state.Anchored.searchList, className: this.state.Anchored.classes.searchList })));
this.state.__ANCHOREDr = location.pathname;
this.state.AnchorSearch = anchored;
_jquery2['default'].extend(true, this.state, props);
}
_createClass(Tagged, [{
key: 'render',
value: function render() {
// return React.cloneElement(Component, this.props)
return this.state.AnchorSearch;
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(props) {
var clean = location.pathname;
if (clean !== this.state.__ANCHOREDr) {
this.setState({
__ANCHOREDr: clean
});
this._update = true;
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
if (this._update) {
this.onUpdate();
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
this.onUpdate();
this.onMount();
}
}, {
key: 'onUpdate',
value: function onUpdate() {
var thisComponent = this;
this._update = false;
/**
* set some values on mount and update
* instead of on every listen event
* **/
thisComponent.setVars();
}
}, {
key: 'onMount',
value: function onMount() {
var thisComponent = this;
/**
* Search Bar
* takes the value from input and first searches for
* a match in anchor names then a full text search
* */
// catch menu clicks
(0, _jquery2['default'])(document).on('click', '.catchMenuClick a', function (e) {
thisComponent.catchMenuClick(e);
});
// hide the results when clicked outside
(0, _jquery2['default'])(document).on('mouseup', 'body', function (e) {
thisComponent.hideSearchList(e);
});
// jump to first anchor on page that matches and give a list of matches
(0, _jquery2['default'])(document).on('click input focus', '#' + thisComponent.state.Anchored.searchBar + ' input', function (e) {
thisComponent.wordWait(e.target.value);
});
// open menu on single click
(0, _jquery2['default'])(document).on('click', '#TSWrapperLeft', function (e) {
thisComponent.checkMenu();
});
// show search on double click
(0, _jquery2['default'])(document).on('click', '#TSWrapperRight', function (e) {
thisComponent.checkTyping();
});
}
}, {
key: 'setVars',
value: function setVars() {
var thisComponent = this;
thisComponent.$list = (0, _jquery2['default'])('#' + this.state.Anchored.searchBar + ' #' + this.state.Anchored.searchList);
thisComponent.$searchDiv = (0, _jquery2['default'])('#' + this.state.Anchored.searchBar);
thisComponent.$searchInput = thisComponent.$searchDiv.find('input');
thisComponent.$allAnchors = (0, _jquery2['default'])(thisComponent.state.Anchored.tagSelector);
thisComponent.$wrapper = (0, _jquery2['default'])('#TSWrapper');
return true;
}
}, {
key: 'checkTyping',
value: function checkTyping() {
if (this._typingBit) {
this.disAllowTyping();
} else {
this.allowTyping();
}
}
}, {
key: 'allowTyping',
value: function allowTyping() {
this._typingBit = true;
this.$wrapper.hide();
this.$searchInput.focus();
}
}, {
key: 'disAllowTyping',
value: function disAllowTyping() {
this._typingBit = false;
this.$wrapper.show();
}
}, {
key: 'checkMenu',
value: function checkMenu() {
if (this._menuBit) {
this.hideMenu();
} else {
this.showMenu();
}
}
}, {
key: 'showMenu',
value: function showMenu() {
this._menuBit = true;
this.searchTags(this.$searchInput.val());
}
}, {
key: 'hideMenu',
value: function hideMenu() {
this._menuBit = false;
this.$list.hide();
}
}, {
key: 'catchMenuClick',
value: function catchMenuClick(e) {
var thisComponent = this;
// catch a menu click and close any menus
thisComponent.hideMenu();
thisComponent.disAllowTyping();
// clean search bar status
thisComponent.$searchInput.css('background-color', _styles2['default'].input.backgroundColor);
}
}, {
key: 'hideSearchList',
value: function hideSearchList(e) {
var thisComponent = this;
var $list = thisComponent.$list;
var $searchDiv = thisComponent.$searchDiv;
if (!$list.is(e.target) // if the target of the click isn't the container...
&& $list.has(e.target).length === 0 && ( // ... nor a descendant of the container
!$searchDiv.is(e.target) // if the target of the click isn't the main div...
&& $searchDiv.has(e.target).length === 0) // if the target of the click isn't the input...
) {
thisComponent.hideMenu();
(0, _jquery2['default'])('#' + thisComponent.state.Anchored.searchBar + ' input').css('background-color', _styles2['default'].input.backgroundColor);
thisComponent.disAllowTyping();
return;
}
}
}, {
key: 'wordWait',
value: function wordWait(entry) {
var thisComponent = this;
if (!thisComponent._limiters) {
thisComponent._limiters = {
typed: entry
};
// open the list
//console.log('entry search')
return thisComponent.searchTags(entry);
}
var useMe = thisComponent._limiters;
var now = new Date().getTime();
// save the search term until done typing
useMe.typed = entry;
// kill the current interval
clearTimeout(thisComponent._limiters.interval);
// force search after specified time
if (useMe.force < now) {
//console.log('force search')
useMe.force = new Date().getTime() + this.state.Anchored.forceSearch;
thisComponent.searchTags(entry);
return false;
}
// update the forced search
useMe.force = new Date().getTime() + this.state.Anchored.forceSearch;
// set the interval to run the search
useMe.interval = setTimeout(function () {
//console.log('interval search')
thisComponent.searchTags(useMe.typed);
clearTimeout(thisComponent._limiters.interval);
}, 250);
}
}, {
key: 'searchTags',
value: function searchTags(search) {
var thisComponent = this;
var $list = thisComponent.$list;
var $searchInput = thisComponent.$searchInput;
var $allAnchors = thisComponent.$allAnchors;
var searchAnchors = {};
var isWide = document.body.clientWidth > 480;
// our search term fixed up
var searchedFor = search.replace('.', ' ').replace('-', ' ').toLowerCase();
var $firstAnchor = false;
var aBit = false; // bit for anchor presence
var bBit = false; // bit for blob search results presence
$list.html('');
// set display names
var mainHeader = undefined;
if (location.pathname.search('api') > -1) {
mainHeader = 'Method';
} else {
mainHeader = 'Anchor';
}
var ustyle = thisComponent.stringClassFromObject(thisComponent.state.Anchored.styles['li:heading']);
var uclass = thisComponent.state.Anchored.classes['li:heading'];
// create the method ul
var $ul = (0, _jquery2['default'])(document.createElement("ul")).css(thisComponent.state.Anchored.styles.ul).addClass('catchMenuClick ' + thisComponent.state.Anchored.classes.ul);
$ul.append('<li class="' + uclass + '" style="' + ustyle + '">' + mainHeader + ' Matches</li>');
// create the search blob ui
var $ul2 = (0, _jquery2['default'])(document.createElement("ul")).css(thisComponent.state.Anchored.styles.ul).addClass('catchMenuClick ' + thisComponent.state.Anchored.classes.ul);
$ul2.append('<li class="' + uclass + '" style="' + ustyle + '">Search Matches</li>');
// store all li in case of no matches
var allAnchors = (0, _jquery2['default'])(document.createElement("ul")).css(thisComponent.state.Anchored.styles.ul).addClass('catchMenuClick ' + thisComponent.state.Anchored.classes.ul);
allAnchors.append('<li class="' + uclass + '" style="' + ustyle + '">' + mainHeader + 's</li>');
// create search lists
$allAnchors.each(function (k, v) {
var $anchor = (0, _jquery2['default'])(v);
var text = $anchor.nextUntil(thisComponent.state.Anchored.contextTextUntilTag).andSelf().text();
// set display names
var name = $anchor[0][thisComponent.state.Anchored.nameFromTagAttr] || '';
var nameFromTag = $anchor[0][thisComponent.state.Anchored.nameFromTagAttr] || '';
// is the displayed name from the next tag
if (thisComponent.state.nameFromNextTag) {
var _$next = $anchor.next();
} else {
var _$next2 = $anchor;
}
if ('string' === typeof thisComponent.state.Anchored.nameFromTag && thisComponent.state.Anchored.nameFromTag.indexOf($next.prop("tagName")) > -1) {
nameFromTag = $next.clone().children(thisComponent.state.Anchored.nameFromTagSaveChildren).remove().end()[0][thisComponent.state.Anchored.nameFromTagAttr];
}
var listyle = thisComponent.stringClassFromObject(thisComponent.state.Anchored.styles['li']);
var liclass = thisComponent.state.Anchored.classes['li'];
var astyle = thisComponent.stringClassFromObject(thisComponent.state.Anchored.styles['li:a']);
var aclass = thisComponent.state.Anchored.classes['li:a'];
var cstyle = thisComponent.stringClassFromObject(thisComponent.state.Anchored.styles['context']);
var cclass = thisComponent.state.Anchored.classes['context'];
// large blurb
var itemDesc = '<li class="' + liclass + '" style="' + listyle + '"><a class="' + aclass + '" style="' + astyle + '"href="#' + name + '" >' + nameFromTag + '</a><div class="' + cclass + '" style="' + cstyle + '">' + _lodash2['default'].trunc(text, { 'length': 150, 'separator': ' ' }) + '</div></li>';
// smal blurg
var item = '<li class="' + liclass + '" style="' + listyle + '"><a class="' + aclass + '" style="' + astyle + '"href="#' + name + '" >' + nameFromTag + '</a><div class="' + cclass + '" style="' + cstyle + '">' + _lodash2['default'].trunc(text, { 'length': 150, 'separator': ' ' }) + '</div></li>';
// full text search
if (searchedFor !== '' && text !== '') {
var searchArray = searchedFor.split(' ');
if (!Array.isArray(searchArray)) {
searchArray = [];
}
var wordy = searchArray.some(function (word) {
if (text.toLowerCase().search(word) > -1) {
$ul2.append(itemDesc);
return true;
}
return false;
});
}
// populate method list
if (searchedFor !== '' && name.replace('-', ' ').replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase().search(searchedFor) > -1) {
$ul.append(item);
if (!$firstAnchor) {
$firstAnchor = $anchor;
}
}
allAnchors.append(item);
});
// set blob bit
bBit = $ul2[0].childElementCount > 1;
// set method bit
aBit = $ul[0].childElementCount > 1;
if (aBit && $firstAnchor[0].name) {
(function () {
var goTo = location.pathname + '#' + $firstAnchor[0].name;
// do we have history?
var pushHistory = undefined;
var replaceHistory = undefined;
var _history = false;
if ('object' === _jquery2['default'].type(thisComponent.props.history)) {
if ('function' === _jquery2['default'].type(thisComponent.props.history.pushState)) {
pushHistory = function () {
console.log('push history');
thisComponent.props.history.pushState(null, goTo);
};
replaceHistory = function () {
console.log('replace history');
thisComponent.props.history.replaceState(null, goTo);
};
_history = true;
}
}
// push the anchor
if (!isWide || thisComponent.state.Anchored.useLocation === false) {
// mobiles loses focus on history & location so just move with scrollTop
(0, _jquery2['default'])(document).scrollTop($firstAnchor.offset().top);
if (_history) {
replaceHistory();
}
} else {
// use window and send to history if requested
window.location.href = goTo;
if (_history) {
replaceHistory();
}
}
// we lose focus on mobile when a location change happens
$searchInput.blur().focus();
// set background to normal
$searchInput.css('background-color', _styles2['default'].active.backgroundColor);
})();
} else if (!bBit) {
aBit = true;
$ul = allAnchors;
$searchInput.css('background-color', _styles2['default'].caution.backgroundColor);
}
// reset the list so scroll goes to top
$list[0].innerHTML = '';
if (!isWide || (!bBit || !aBit)) {
if (aBit) {
$list.append($ul);
}
if (bBit) {
$list.append($ul2);
}
} else {
// float left methods
$list.append((0, _jquery2['default'])(document.createElement("div")).css({ float: 'left', width: '50%' }).append($ul));
// float left blob search
$list.append((0, _jquery2['default'])(document.createElement("div")).css({ float: 'left', width: '50%' }).append($ul2));
}
$list.show();
}
}, {
key: 'stringClassFromObject',
value: function stringClassFromObject(cobj) {
var str = '';
_jquery2['default'].each(cobj, function (k, v) {
if (k) str += _lodash2['default'].kebabCase(k) + ':' + v + '; ';
});
return str;
}
}, {
key: 'rateLimited',
value: function rateLimited(id, time) {
/**
* keeps a timer per id
* returns true if rate limited
* returns false if ok to run or new
* **/
var timer = new Date().getTime();
if ('number' === _jquery2['default'].type(this._limiters[id])) {
if (timer - this._limiters[id] < time) {
return true;
} else {
this._limiters[id] = timer;
return false;
}
} else {
this._limiters[id] = timer;
return false;
}
}
}]);
return Tagged;
})(_react2['default'].Component);
exports['default'] = Tagged;
module.exports = exports['default'];
},{"./classes":2,"./styles":3,"lodash":5}],5:[function(require,module,exports){
(function (global){
/**
* @license
* lodash 3.10.1 (Custom Build) <https://lodash.com/>
* Build: `lodash modern -d -o ./index.js`
* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <https://lodash.com/license>
*/
;(function() {
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
var undefined;
/** Used as the semantic version number. */
var VERSION = '3.10.1';
/** Used to compose bitmasks for wrapper metadata. */
var BIND_FLAG = 1,
BIND_KEY_FLAG = 2,
CURRY_BOUND_FLAG = 4,
CURRY_FLAG = 8,
CURRY_RIGHT_FLAG = 16,
PARTIAL_FLAG = 32,
PARTIAL_RIGHT_FLAG = 64,
ARY_FLAG = 128,
REARG_FLAG = 256;
/** Used as default options for `_.trunc`. */
var DEFAULT_TRUNC_LENGTH = 30,
DEFAULT_TRUNC_OMISSION = '...';
/** Used to detect when a function becomes hot. */
var HOT_COUNT = 150,
HOT_SPAN = 16;
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;
/** Used to indicate the type of lazy iteratees. */
var LAZY_FILTER_FLAG = 1,
LAZY_MAP_FLAG = 2;
/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';
/** Used as the internal argument placeholder. */
var PLACEHOLDER = '__lodash_placeholder__';
/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
arrayTag = '[object Array]',
boolTag = '[object Boolean]',
dateTag = '[object Date]',
errorTag = '[object Error]',
funcTag = '[object Function]',
mapTag = '[object Map]',
numberTag = '[object Number]',
objectTag = '[object Object]',
regexpTag = '[object RegExp]',
setTag = '[object Set]',
stringTag = '[object String]',
weakMapTag = '[object WeakMap]';
var arrayBufferTag = '[object ArrayBuffer]',
float32Tag = '[object Float32Array]',
float64Tag = '[object Float64Array]',
int8Tag = '[object Int8Array]',
int16Tag = '[object Int16Array]',
int32Tag = '[object Int32Array]',
uint8Tag = '[object Uint8Array]',
uint8ClampedTag = '[object Uint8ClampedArray]',
uint16Tag = '[object Uint16Array]',
uint32Tag = '[object Uint32Array]';
/** Used to match empty string literals in compiled template source. */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/** Used to match HTML entities and HTML characters. */
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
reUnescapedHtml = /[&<>"'`]/g,
reHasEscapedHtml = RegExp(reEscapedHtml.source),
reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
/** Used to match template delimiters. */
var reEscape = /<%-([\s\S]+?)%>/g,
reEvaluate = /<%([\s\S]+?)%>/g,
reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
reIsPlainProp = /^\w*$/,
rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
/**
* Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns)
* and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern).
*/
var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,
reHasRegExpChars = RegExp(reRegExpChars.source);
/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;
/** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match `RegExp` flags from their coerced string values. */
var reFlags = /\w*$/;
/** Used to detect hexadecimal string values. */
var reHasHexPrefix = /^0[xX]/;
/** Used to detect host constructors (Safari > 5). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;
/** Used to detect unsigned integer values. */
var reIsUint = /^\d+$/;
/** Used to match latin-1 supplementary letters (excluding mathematical operators). */
var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
/** Used to ensure capturing order of template delimiters. */
var reNoMatch = /($^)/;
/** Used to match unescaped characters in compiled string literals. */
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
/** Used to match words to create compound words. */
var reWords = (function() {
var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
}());
/** Used to assign default `context` object properties. */
var contextProps = [
'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',
'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite',
'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap'
];
/** Used to make template sourceURLs easier to identify. */
var templateCounter = -1;
/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dateTag] = typedArrayTags[errorTag] =
typedArrayTags[funcTag] = typedArrayTags[mapTag] =
typedArrayTags[numberTag] = typedArrayTags[objectTag] =
typedArrayTags[regexpTag] = typedArrayTags[setTag] =
typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
/** Used to identify `toStringTag` values supported by `_.clone`. */
var cloneableTags = {};
cloneableTags[argsTag] = cloneableTags[arrayTag] =
cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
cloneableTags[dateTag] = cloneableTags[float32Tag] =
cloneableTags[float64Tag] = cloneableTags[int8Tag] =
cloneableTags[int16Tag] = cloneableTags[int32Tag] =
cloneableTags[numberTag] = cloneableTags[objectTag] =
cloneableTags[regexpTag] = cloneableTags[stringTag] =
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
cloneableTags[errorTag] = cloneableTags[funcTag] =
cloneableTags[mapTag] = cloneableTags[setTag] =
cloneableTags[weakMapTag] = false;
/** Used to map latin-1 supplementary letters to basic latin letters. */
var deburredLetters = {
'\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
'\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
'\xc7': 'C', '\xe7': 'c',
'\xd0': 'D', '\xf0': 'd',
'\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
'\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
'\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
'\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
'\xd1': 'N', '\xf1': 'n',
'\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
'\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
'\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
'\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
'\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
'\xc6': 'Ae', '\xe6': 'ae',
'\xde': 'Th', '\xfe': 'th',
'\xdf': 'ss'
};
/** Used to map characters to HTML entities. */
var htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'`': '`'
};
/** Used to map HTML entities to characters. */
var htmlUnescapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
''': "'",
'`': '`'
};
/** Used to determine if values are of the language type `Object`. */
var objectTypes = {
'function': true,
'object': true
};
/** Used to escape characters for inclusion in compiled regexes. */
var regexpEscapes = {
'0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34',
'5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39',
'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46',
'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66',
'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78'
};
/** Used to escape characters for inclusion in compiled string literals. */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/** Detect free variable `exports`. */
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/** Detect free variable `global` from Node.js. */
var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
/** Detect free variable `self`. */
var freeSelf = objectTypes[typeof self] && self && self.Object && self;
/** Detect free variable `window`. */
var freeWindow = objectTypes[typeof window] && window && window.Object && window;
/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
/**
* Used as a reference to the global object.
*
* The `this` value is used if it's the global object to avoid Greasemonkey's
* restricted `window` object, otherwise the `window` object is used.
*/
var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `compareAscending` which compares values and
* sorts them in ascending order without guaranteeing a stable sort.
*
* @private
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {number} Returns the sort order indicator for `value`.
*/
function baseCompareAscending(value, other) {
if (value !== other) {
var valIsNull = value === null,
valIsUndef = value === undefined,
valIsReflexive = value === value;
var othIsNull = other === null,
othIsUndef = other === undefined,
othIsReflexive = other === other;
if ((value > other && !othIsNull) || !valIsReflexive ||
(valIsNull && !othIsUndef && othIsReflexive) ||
(valIsUndef && othIsReflexive)) {
return 1;
}
if ((value < other && !valIsNull) || !othIsReflexive ||
(othIsNull && !valIsUndef && valIsReflexive) ||
(othIsUndef && valIsReflexive)) {
return -1;
}
}
return 0;
}
/**
* The base implementation of `_.findIndex` and `_.findLastIndex` without
* support for callback shorthands and `this` binding.
*
* @private
* @param {Array} array The array to search.
* @param {Function} predicate The function invoked per iteration.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function baseFindIndex(array, predicate, fromRight) {
var length = array.length,
index = fromRight ? length : -1;
while ((fromRight ? index-- : ++index < length)) {
if (predicate(array[index], index, array)) {
return index;
}
}
return -1;
}
/**
* The base implementation of `_.indexOf` without support for binary searches.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
if (value !== value) {
return indexOfNaN(array, fromIndex);
}
var index = fromIndex - 1,
length = array.length;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* The base implementation of `_.isFunction` without support for environments
* with incorrect `typeof` results.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
*/
function baseIsFunction(value) {
// Avoid a Chakra JIT bug in compatibility modes of IE 11.
// See https://github.com/jashkenas/underscore/issues/1621 for more details.
return typeof value == 'function' || false;
}
/**
* Converts `value` to a string if it's not one. An empty string is returned
* for `null` or `undefined` values.
*
* @private
* @param {*} value The value to process.
* @returns {string} Returns the string.
*/
function baseToString(value) {
return value == null ? '' : (value + '');
}
/**
* Used by `_.trim` and `_.trimLeft` to get the index of the first character
* of `string` that is not found in `chars`.
*
* @private
* @param {string} string The string to inspect.
* @param {string} chars The characters to find.
* @returns {number} Returns the index of the first character not found in `chars`.
*/
function charsLeftIndex(string, chars) {
var index = -1,
length = string.length;
while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
return index;
}
/**
* Used by `_.trim` and `_.trimRight` to get the index of the last character
* of `string` that is not found in `chars`.
*
* @private
* @param {string} string The string to inspect.
* @param {string} chars The characters to find.
* @returns {number} Returns the index of the last character not found in `chars`.
*/
function charsRightIndex(string, chars) {
var index = string.length;
while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
return index;
}
/**
* Used by `_.sortBy` to compare transformed elements of a collection and stable
* sort them in ascending order.
*
* @private
* @param {Object} object The object to compare.
* @param {Object} other The other object to compare.
* @returns {number} Returns the sort order indicator for `object`.
*/
function compareAscending(object, other) {
return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
}
/**
* Used by `_.sortByOrder` to compare multiple properties of a value to another
* and stable sort them.
*
* If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise,
* a value is sorted in ascending order if its corresponding order is "asc", and
* descending if "desc".
*
* @private
* @param {Object} object The object to compare.
* @param {Object} other The other object to compare.
* @param {boolean[]} orders The order to sort by for each property.
* @returns {number} Returns the sort order indicator for `object`.
*/
function compareMultiple(object, other, orders) {
var index = -1,
objCriteria = object.criteria,
othCriteria = other.criteria,
length = objCriteria.length,
ordersLength = orders.length;
while (++index < length) {
var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
if (result) {
if (index >= ordersLength) {
return result;
}
var order = orders[index];
return result * ((order === 'asc' || order === true) ? 1 : -1);
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to provide the same value for
// `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
// for more details.
//
// This also ensures a stable sort in V8 and other engines.
// See https://code.google.com/p/v8/issues/detail?id=90 for more details.
return object.index - other.index;
}
/**
* Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
*
* @private
* @param {string} letter The matched letter to deburr.
* @returns {string} Returns the deburred letter.
*/
function deburrLetter(letter) {
return deburredLetters[letter];
}
/**
* Used by `_.escape` to convert characters to HTML entities.
*
* @private
* @param {string} chr The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeHtmlChar(chr) {
return htmlEscapes[chr];
}
/**
* Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes.
*
* @private
* @param {string} chr The matched character to escape.
* @param {string} leadingChar The capture group for a leading character.
* @param {string} whitespaceChar The capture group for a whitespace character.
* @returns {string} Returns the escaped character.
*/
function escapeRegExpChar(chr, leadingChar, whitespaceChar) {
if (leadingChar) {
chr = regexpEscapes[chr];
} else if (whitespaceChar) {
chr = stringEscapes[chr];
}
return '\\' + chr;
}
/**
* Used by `_.template` to escape characters for inclusion in compiled string literals.
*
* @private
* @param {string} chr The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeStringChar(chr) {
return '\\' + stringEscapes[chr];
}
/**
* Gets the index at which the first occurrence of `NaN` is found in `array`.
*
* @private
* @param {Array} array The array to search.
* @param {number} fromIndex The index to search from.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {number} Returns the index of the matched `NaN`, else `-1`.
*/
function indexOfNaN(array, fromIndex, fromRight) {
var length = array.length,
index = fromIndex + (fromRight ? 0 : -1);
while ((fromRight ? index-- : ++index < length)) {
var other = array[index];
if (other !== other) {
return index;
}
}
return -1;
}
/**
* Checks if `value` is object-like.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
*/
function isObjectLike(value) {
return !!value && typeof value == 'object';
}
/**
* Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a
* character code is whitespace.
*
* @private
* @param {number} charCode The character code to inspect.
* @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.
*/
function isSpace(charCode) {
return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||
(charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
}
/**
* Replaces all `placeholder` elements in `array` with an internal placeholder
* and returns an array of their indexes.
*
* @private
* @param {Array} array The array to modify.
* @param {*} placeholder The placeholder to replace.
* @returns {Array} Returns the new array of placeholder indexes.
*/
function replaceHolders(array, placeholder) {
var index = -1,
length = array.length,
resIndex = -1,
result = [];
while (++index < length) {
if (array[index] === placeholder) {
array[index] = PLACEHOLDER;
result[++resIndex] = index;
}
}
return result;
}
/**
* An implementation of `_.uniq` optimized for sorted arrays without support
* for callback shorthands and `this` binding.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The function invoked per iteration.
* @returns {Array} Returns the new duplicate-value-free array.
*/
function sortedUniq(array, iteratee) {
var seen,
index = -1,
length = array.length,
resIndex = -1,
result = [];
while (++index < length) {
var value = array[index],
computed = iteratee ? iteratee(value, index, array) : value;
if (!index || seen !== computed) {
seen = computed;
result[++resIndex] = value;
}
}
return result;
}
/**
* Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
* character of `string`.
*
* @private
* @param {string} string The string to inspect.
* @returns {number} Returns the index of the first non-whitespace character.
*/
function trimmedLeftIndex(string) {
var index = -1,
length = string.length;
while (++index < length && isSpace(string.charCodeAt(index))) {}
return index;
}
/**
* Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
* character of `string`.
*
* @private
* @param {string} string The string to inspect.
* @r