change some typings, rename $.fn.animatedScrollTop to $.fn.animateScrollTop

This commit is contained in:
David Sevilla Martin 2020-03-21 16:42:24 -04:00
parent 83d0345e93
commit 0dc846bc4a
No known key found for this signature in database
GPG Key ID: F764F1417E16B15F
17 changed files with 121 additions and 157 deletions

3
js/dist/admin.js vendored
View File

@ -11812,7 +11812,7 @@ $.fn.hover = function (hover, leave) {
}; // add animated scroll
$.fn.animatedScrollTop = function (to, duration, callback) {
$.fn.animateScrollTop = function (to, duration, callback) {
if (duration === void 0) {
duration = $.fx.speeds._default;
}
@ -11848,7 +11848,6 @@ $.fn.extend = $.extend.bind($);
* Enable special events on Zepto
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
*/
// @ts-ignore
$.event.special = $.event.special || {};
var bindBeforeSpecialEvents = $.fn.bind;

File diff suppressed because one or more lines are too long

104
js/dist/forum.js vendored
View File

@ -12767,13 +12767,16 @@ var Application = /*#__PURE__*/function () {
basePath = '';
}
m.mount(document.getElementById('modal'), this.modal = new _components_ModalManager__WEBPACK_IMPORTED_MODULE_19__["default"]());
m.mount(document.getElementById('alerts'), this.alerts = new _components_AlertManager__WEBPACK_IMPORTED_MODULE_22__["default"]({
var $modal = document.getElementById('modal');
var $alerts = document.getElementById('alerts');
var $content = document.getElementById('content');
if ($modal) m.mount($modal, this.modal = new _components_ModalManager__WEBPACK_IMPORTED_MODULE_19__["default"]());
if ($alerts) m.mount($alerts, this.alerts = new _components_AlertManager__WEBPACK_IMPORTED_MODULE_22__["default"]({
oninit: function oninit(vnode) {
return _this3.alerts = vnode.state;
}
}));
m.route(document.getElementById('content'), basePath + '/', Object(_utils_mapRoutes__WEBPACK_IMPORTED_MODULE_6__["default"])(this.routes, basePath)); // Add a class to the body which indicates that the page has been scrolled
if ($content) m.route($content, basePath + '/', Object(_utils_mapRoutes__WEBPACK_IMPORTED_MODULE_6__["default"])(this.routes, basePath)); // Add a class to the body which indicates that the page has been scrolled
// down.
new _utils_ScrollListener__WEBPACK_IMPORTED_MODULE_10__["default"](function (top) {
@ -13128,8 +13131,6 @@ __webpack_require__.r(__webpack_exports__);
/**
* The `Model` class represents a local data resource. It provides methods to
* persist changes via the API.
*
* @abstract
*/
var Model = /*#__PURE__*/function () {
/**
@ -13151,18 +13152,14 @@ var Model = /*#__PURE__*/function () {
*/
/**
* @param {Object} data A resource object from the API.
* @param {Store} store The data store that this model should be persisted to.
* @param data A resource object from the API.
* @param store The data store that this model should be persisted to.
*/
function Model(data, store) {
if (data === void 0) {
data = {};
}
if (store === void 0) {
store = null;
}
this.data = void 0;
this.payload = void 0;
this.freshness = void 0;
@ -13197,7 +13194,6 @@ var Model = /*#__PURE__*/function () {
* Merge new data into this model locally.
*
* @param data A resource object to merge into this model
* @public
*/
;
@ -13232,7 +13228,7 @@ var Model = /*#__PURE__*/function () {
/**
* Merge new attributes into this model locally.
*
* @param {Object} attributes The attributes to merge.
* @param attributes The attributes to merge.
*/
;
@ -13247,7 +13243,6 @@ var Model = /*#__PURE__*/function () {
* @param attributes The attributes to save. If a 'relationships' key
* exists, it will be extracted and relationships will also be saved.
* @param [options]
* @return {Promise}
*/
;
@ -13358,7 +13353,7 @@ var Model = /*#__PURE__*/function () {
/**
* Generate a function which returns the value of the given attribute.
*
* @param {String} name
* @param name
* @param [transform] A function to transform the attribute value
*/
;
@ -13384,7 +13379,7 @@ var Model = /*#__PURE__*/function () {
if (this.data.relationships) {
var relationship = this.data.relationships[name];
if (relationship) {
if (relationship && !Array.isArray(relationship.data)) {
return app.store.getById(relationship.data.type, relationship.data.id);
}
}
@ -13407,7 +13402,7 @@ var Model = /*#__PURE__*/function () {
if (this.data.relationships) {
var relationship = this.data.relationships[name];
if (relationship) {
if (relationship && Array.isArray(relationship.data)) {
return relationship.data.map(function (data) {
return app.store.getById(data.type, data.id);
});
@ -13724,10 +13719,6 @@ var Translator = /*#__PURE__*/function () {
};
_proto.trans = function trans(id, parameters) {
if (parameters === void 0) {
parameters = null;
}
var translation = this.translations[id];
if (translation) {
@ -13738,10 +13729,6 @@ var Translator = /*#__PURE__*/function () {
};
_proto.transText = function transText(id, parameters) {
if (parameters === void 0) {
parameters = null;
}
return Object(_utils_extractText__WEBPACK_IMPORTED_MODULE_2__["default"])(this.trans(id, parameters));
};
@ -13749,7 +13736,6 @@ var Translator = /*#__PURE__*/function () {
var translation = this.translations[id];
if (translation) {
number = parseInt(number, 10);
translation = this.pluralize(translation, number);
return this.apply(translation, parameters || {});
}
@ -17256,7 +17242,7 @@ $.fn.hover = function (hover, leave) {
}; // add animated scroll
$.fn.animatedScrollTop = function (to, duration, callback) {
$.fn.animateScrollTop = function (to, duration, callback) {
if (duration === void 0) {
duration = $.fx.speeds._default;
}
@ -17292,7 +17278,6 @@ $.fn.extend = $.extend.bind($);
* Enable special events on Zepto
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
*/
// @ts-ignore
$.event.special = $.event.special || {};
var bindBeforeSpecialEvents = $.fn.bind;
@ -18815,8 +18800,8 @@ var DiscussionPage = /*#__PURE__*/function (_Page) {
}
_this = _Page.call.apply(_Page, [this].concat(args)) || this;
_this.discussion = void 0;
_this.near = void 0;
_this.discussion = null;
_this.near = null;
_this.stream = void 0;
_this.scrubber = void 0;
_this.includedPosts = [];
@ -18999,23 +18984,19 @@ var DiscussionPage = /*#__PURE__*/function (_Page) {
var $list = $(vnode.dom); // When the mouse enters and leaves the discussions pane, we want to show
// and hide the pane respectively. We also create a 10px 'hot edge' on the
// left of the screen to activate the pane.
var pane = app.pane;
$list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
var hotEdge = function hotEdge(e) {
if (e.pageX < 10) pane.show();
};
$(document).on('mousemove', hotEdge);
vnode.dom.onunload = function () {
return $(document).off('mousemove', hotEdge);
}; // If the discussion we are viewing is listed in the discussion list, then
// TODO pane
// const pane = app.pane;
// $list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
//
// const hotEdge = e => {
// if (e.pageX < 10) pane.show();
// };
// $(document).on('mousemove', hotEdge);
// vnode.dom.onunload = () => $(document).off('mousemove', hotEdge);
// If the discussion we are viewing is listed in the discussion list, then
// we will make sure it is visible in the viewport – if it is not we will
// scroll the list down to it.
var $discussion = $list.find('.DiscussionListItem.active');
if ($discussion.length) {
@ -21633,7 +21614,7 @@ var PostStream = /*#__PURE__*/function (_Component) {
$container.scrollTop(top);
resolve();
} else if (top !== scrollTop) {
$container.animatedScrollTop(top, 'fast', resolve);
$container.animateScrollTop(top, 'fast', resolve);
} else {
resolve();
}
@ -21876,6 +21857,10 @@ var PostStreamScrubber = /*#__PURE__*/function (_Component) {
;
_proto.update = function update(scrollTop) {
if (scrollTop === void 0) {
scrollTop = 0;
}
var stream = this.stream;
var marginTop = stream.getMarginTop();
var viewportTop = scrollTop + marginTop;
@ -21924,6 +21909,7 @@ var PostStreamScrubber = /*#__PURE__*/function (_Component) {
var time = $this.data('time');
if (time) period = time;
return true;
});
this.index = index;
this.visible = visible;
@ -22544,11 +22530,11 @@ var Search = /*#__PURE__*/function (_Component) {
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
_this.value = m.prop('');
_this.hasFocus = false;
_this.sources = null;
_this.sources = void 0;
_this.loadingSources = 0;
_this.searched = [];
_this.index = 0;
_this.navigator = void 0;
_this.navigator = new _utils_KeyboardNavigatable__WEBPACK_IMPORTED_MODULE_4__["default"]();
_this.searchTimeout = void 0;
return _this;
}
@ -22619,7 +22605,6 @@ var Search = /*#__PURE__*/function (_Component) {
search.setIndex(search.selectableItems().index(this));
});
var $input = this.$('input');
this.navigator = new _utils_KeyboardNavigatable__WEBPACK_IMPORTED_MODULE_4__["default"]();
this.navigator.onUp(function () {
return _this3.setIndex(_this3.getCurrentNumericIndex() - 1, true);
}).onDown(function () {
@ -22633,7 +22618,7 @@ var Search = /*#__PURE__*/function (_Component) {
search.searchTimeout = setTimeout(function () {
if (search.searched.indexOf(query) !== -1) return;
if (query.length >= 3) {
if (query.length >= 3 && search.sources) {
search.sources.map(function (source) {
if (!source.search) return;
search.loadingSources++;
@ -22655,8 +22640,6 @@ var Search = /*#__PURE__*/function (_Component) {
}
/**
* Get the active search in the app's current controller.
*
* @return {String}
*/
;
@ -22709,8 +22692,6 @@ var Search = /*#__PURE__*/function (_Component) {
}
/**
* Get all of the search result items that are selectable.
*
* @return {jQuery}
*/
;
@ -22719,8 +22700,6 @@ var Search = /*#__PURE__*/function (_Component) {
}
/**
* Get the position of the currently selected search result item.
*
* @return {Integer}
*/
;
@ -22729,9 +22708,6 @@ var Search = /*#__PURE__*/function (_Component) {
}
/**
* Get the <li> in the search results with the given index (numeric or named).
*
* @param {String} index
* @return {DOMElement}
*/
;
@ -22767,7 +22743,7 @@ var Search = /*#__PURE__*/function (_Component) {
}
var $item = $items.removeClass('active').eq(fixedIndex).addClass('active');
this.index = $item.attr('data-index') || fixedIndex;
this.index = Number($item.attr('data-index') || fixedIndex);
if (scrollToItem) {
var dropdownScroll = $dropdown.scrollTop();
@ -22784,9 +22760,7 @@ var Search = /*#__PURE__*/function (_Component) {
}
if (typeof scrollTop !== 'undefined') {
$dropdown.animate({
scrollTop: scrollTop
}, 100);
$dropdown.animateScrollTop(scrollTop, 100);
}
}
};
@ -24215,9 +24189,9 @@ var History = /*#__PURE__*/function () {
/**
* Push an item to the top of the stack.
*
* @param {String} name The name of the route.
* @param {String} title The title of the route.
* @param {String} [url] The URL of the route. The current URL will be used if
* @param name The name of the route.
* @param title The title of the route.
* @param [url] The URL of the route. The current URL will be used if
* not provided.
*/
;

File diff suppressed because one or more lines are too long

View File

@ -139,11 +139,15 @@ export default abstract class Application {
}
mount(basePath = '') {
m.mount(document.getElementById('modal'), (this.modal = new ModalManager()));
const $modal = document.getElementById('modal');
const $alerts = document.getElementById('alerts');
const $content = document.getElementById('content');
m.mount(document.getElementById('alerts'), (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) })));
if ($modal) m.mount($modal, (this.modal = new ModalManager()));
m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath));
if ($alerts) m.mount($alerts, (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) })));
if ($content) m.route($content, basePath + '/', mapRoutes(this.routes, basePath));
// Add a class to the body which indicates that the page has been scrolled
// down.
@ -210,7 +214,7 @@ export default abstract class Application {
if (params.hasOwnProperty(key) && !params[key]) delete params[key];
}
const queryString = m.buildQueryString(params);
const queryString = m.buildQueryString(params as Mithril.Params);
const prefix = m.route.prefix === '' ? this.forum.attribute('basePath') : '';
return prefix + url + (queryString ? '?' + queryString : '');
@ -221,8 +225,8 @@ export default abstract class Application {
*
* @see https://mithril.js.org/request.html
*/
request(originalOptions: Mithril.RequestOptions | any): Promise<any> {
const options: Mithril.RequestOptions = Object.assign({}, originalOptions);
request(originalOptions: Mithril.RequestOptions<JSON> | any): Promise<any> {
const options: Mithril.RequestOptions<JSON> | any = Object.assign({}, originalOptions);
// Set some default options if they haven't been overridden. We want to
// authenticate all requests with the session token. We also want all
@ -230,7 +234,7 @@ export default abstract class Application {
// prevent redraws from occurring.
options.background = options.background || true;
extend(options, 'config', (result, xhr: XMLHttpRequest) => xhr.setRequestHeader('X-CSRF-Token', this.session.csrfToken));
extend(options, 'config', (result, xhr: XMLHttpRequest) => xhr.setRequestHeader('X-CSRF-Token', this.session.csrfToken!));
// If the method is something like PATCH or DELETE, which not all servers
// and clients support, then we'll send it as a POST request with the
@ -347,7 +351,7 @@ export default abstract class Application {
}
private showDebug(error: RequestError) {
this.alerts.dismiss(this.requestError.alert);
this.alerts.dismiss(this.requestError!.alert);
this.modal.show(RequestErrorModal, { error });
}

View File

@ -65,7 +65,7 @@ export default class Component<T extends ComponentProps = any> implements ClassC
}
render() {
return m(this.constructor, this.props);
return m(this.constructor as typeof Component, this.props);
}
static component(props: ComponentProps | any = {}, children?: Mithril.Children) {

View File

@ -1,9 +1,3 @@
/**
* The `Model` class represents a local data resource. It provides methods to
* persist changes via the API.
*
* @abstract
*/
import Store from './Store';
export interface Identifier {
@ -16,7 +10,11 @@ export interface Data extends Identifier {
relationships?: { [key: string]: { data: Identifier | Identifier[] } };
}
export default class Model {
/**
* The `Model` class represents a local data resource. It provides methods to
* persist changes via the API.
*/
export default abstract class Model {
/**
* The resource object from the API.
*/
@ -39,13 +37,13 @@ export default class Model {
/**
* The data store that this resource should be persisted to.
*/
protected store: Store;
protected store?: Store;
/**
* @param {Object} data A resource object from the API.
* @param {Store} store The data store that this model should be persisted to.
* @param data A resource object from the API.
* @param store The data store that this model should be persisted to.
*/
constructor(data = {}, store = null) {
constructor(data = <Data>{}, store?: Store) {
this.data = data;
this.store = store;
@ -73,9 +71,8 @@ export default class Model {
* Merge new data into this model locally.
*
* @param data A resource object to merge into this model
* @public
*/
pushData(data: {}) {
public pushData(data: {}) {
// Since most of the top-level items in a resource object are objects
// (e.g. relationships, attributes), we'll need to check and perform the
// merge at the second level if that's the case.
@ -105,7 +102,7 @@ export default class Model {
/**
* Merge new attributes into this model locally.
*
* @param {Object} attributes The attributes to merge.
* @param attributes The attributes to merge.
*/
pushAttributes(attributes: any) {
this.pushData({ attributes });
@ -117,7 +114,6 @@ export default class Model {
* @param attributes The attributes to save. If a 'relationships' key
* exists, it will be extracted and relationships will also be saved.
* @param [options]
* @return {Promise}
*/
save(attributes: any, options: any = {}): Promise<Model | Model[]> {
const data: Data = {
@ -208,7 +204,7 @@ export default class Model {
)
.then(() => {
this.exists = false;
this.store.remove(this);
this.store!.remove(this);
});
}
@ -229,7 +225,7 @@ export default class Model {
/**
* Generate a function which returns the value of the given attribute.
*
* @param {String} name
* @param name
* @param [transform] A function to transform the attribute value
*/
static attribute(name: string, transform?: Function): () => any {
@ -253,7 +249,7 @@ export default class Model {
if (this.data.relationships) {
const relationship = this.data.relationships[name];
if (relationship) {
if (relationship && !Array.isArray(relationship.data)) {
return app.store.getById(relationship.data.type, relationship.data.id);
}
}
@ -275,7 +271,7 @@ export default class Model {
if (this.data.relationships) {
const relationship = this.data.relationships[name];
if (relationship) {
if (relationship && Array.isArray(relationship.data)) {
return relationship.data.map(data => app.store.getById(data.type, data.id));
}
}

View File

@ -75,7 +75,7 @@ export default class Store {
* @param query
* @param options
*/
find<T extends Model = Model>(type: string, id?: number | number[] | any, query = {}, options = {}): Promise<T[]> {
find<T extends Model = Model>(type: string, id?: number | number[] | any, query = {}, options = {}): Promise<T | T[]> {
let params = query;
let url = `${app.forum.attribute('apiUrl')}/${type}`;
@ -87,7 +87,7 @@ export default class Store {
url += `/${id}`;
}
return <Promise<T[]>>app
return <Promise<T | T[]>>app
.request(
Object.assign(
{

View File

@ -15,7 +15,7 @@ export default class Translator {
Object.assign(this.translations, translations);
}
trans(id: string, parameters = null) {
trans(id: string, parameters?: any): string | any[] {
const translation = this.translations[id];
if (translation) {
@ -25,16 +25,14 @@ export default class Translator {
return id;
}
transText(id: string, parameters = null) {
transText(id: string, parameters?: any): string {
return extractText(this.trans(id, parameters));
}
transChoice(id: string, number: string | number, parameters: any) {
let translation = this.translations[id];
transChoice(id: string, number: number, parameters: any): string | any[] {
let translation: string = this.translations[id];
if (translation) {
number = parseInt(number, 10);
translation = this.pluralize(translation, number);
return this.apply(translation, parameters || {});
@ -77,7 +75,7 @@ export default class Translator {
return hydrated.filter(part => part);
}
pluralize(translation: string, number: number) {
pluralize(translation: string, number: number): string | undefined {
const sPluralRegex = new RegExp(/^\w+\: +(.+)$/),
cPluralRegex = new RegExp(
/^\s*((\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]]))\s?(.+?)$/
@ -137,7 +135,7 @@ export default class Translator {
return parseInt(number, 10);
}
pluralPosition(number: number, locale: string) {
pluralPosition(number: number, locale: string): number {
if ('pt_BR' === locale) {
locale = 'xbr';
}

View File

@ -11,7 +11,7 @@
* @param element The element to anchor the scroll position to.
* @param callback The callback to run that will change page content.
*/
export default function anchorScroll(element: Element, callback: Function) {
export default function anchorScroll(element: HTMLElement, callback: Function) {
const $window = $(window);
const $el = $(element);

View File

@ -3,7 +3,7 @@ import Tooltip from 'tooltip.js';
// add $.fn.tooltip
$.fn.tooltip = function(option) {
return this.each(function() {
return this.each(function(this: HTMLElement) {
const $this = $(this);
let data = $this.data('bs.tooltip');
const options = (typeof option === 'object' && option) || {};
@ -59,7 +59,7 @@ $.fn.hover = function(hover, leave) {
};
// add animated scroll
$.fn.animatedScrollTop = function(to, duration = $.fx.speeds._default, callback) {
$.fn.animateScrollTop = function(to, duration = $.fx.speeds._default, callback) {
if (typeof to === 'number') to -= window.scrollY || window.pageYOffset;
jump(to, {
@ -94,7 +94,6 @@ $.fn.extend = $.extend.bind($);
* Enable special events on Zepto
* @license Original Copyright 2013 Enideo. Released under dual MIT and GPL licenses.
*/
// @ts-ignore
$.event.special = $.event.special || {};
const bindBeforeSpecialEvents = $.fn.bind;

View File

@ -18,12 +18,12 @@ export default class DiscussionPage extends Page {
/**
* The discussion that is being viewed.
*/
discussion?: Discussion;
discussion: Discussion | null = null;
/**
* The number of the first post that is currently visible in the viewport.
*/
near?: number;
near: number | null = null;
stream!: PostStream;
scrubber!: PostStreamScrubber;
@ -155,7 +155,7 @@ export default class DiscussionPage extends Page {
// component for the first time on page load, then any calls to m.redraw
// will be ineffective and thus any configs (scroll code) will be run
// before stuff is drawn to the page.
setTimeout(this.show.bind(this, preloadedDiscussion), 0);
setTimeout(this.show.bind(this, preloadedDiscussion as Discussion), 0);
} else {
const params = this.requestParams();
@ -219,14 +219,16 @@ export default class DiscussionPage extends Page {
// When the mouse enters and leaves the discussions pane, we want to show
// and hide the pane respectively. We also create a 10px 'hot edge' on the
// left of the screen to activate the pane.
const pane = app.pane;
$list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
const hotEdge = e => {
if (e.pageX < 10) pane.show();
};
$(document).on('mousemove', hotEdge);
vnode.dom.onunload = () => $(document).off('mousemove', hotEdge);
// TODO pane
// const pane = app.pane;
// $list.hover(pane.show.bind(pane), pane.onmouseleave.bind(pane));
//
// const hotEdge = e => {
// if (e.pageX < 10) pane.show();
// };
// $(document).on('mousemove', hotEdge);
// vnode.dom.onunload = () => $(document).off('mousemove', hotEdge);
// If the discussion we are viewing is listed in the discussion list, then
// we will make sure it is visible in the viewport – if it is not we will

View File

@ -13,7 +13,7 @@ export default class PostMeta extends Component<PostProp> {
// When the dropdown menu is shown, select the contents of the permalink
// input so that the user can quickly copy the URL.
const selectPermalink = function(this: Element) {
const selectPermalink = function(this: HTMLElement) {
setTimeout(() =>
$(this)
.parent()

View File

@ -470,7 +470,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
let startNumber;
let endNumber;
this.$('.PostStream-item').each((index, item: Element) => {
this.$('.PostStream-item').each((index, item: HTMLElement) => {
const $item = $(item);
const top = $item.offset().top;
const height = $item.outerHeight(true);
@ -557,7 +557,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
$container.scrollTop(top);
resolve();
} else if (top !== scrollTop) {
$container.animatedScrollTop(top, 'fast', resolve);
$container.animateScrollTop(top, 'fast', resolve);
} else {
resolve();
}

View File

@ -5,6 +5,7 @@ import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
import formatNumber from '../../common/utils/formatNumber';
import PostStream from './PostStream';
import { EventHandler } from '../../common/utils/Evented';
/**
* The `PostStreamScrubber` component displays a scrubber which can be used to
* navigate/scrub through a post stream.
@ -176,7 +177,7 @@ export default class PostStreamScrubber extends Component {
* Update the index/visible/description properties according to the window's
* current scroll position.
*/
update(scrollTop?: number) {
update(scrollTop: number = 0) {
const stream = this.stream;
const marginTop = stream.getMarginTop();
@ -195,7 +196,7 @@ export default class PostStreamScrubber extends Component {
// Now loop through each of the items in the discussion. An 'item' is
// either a single post or a 'gap' of one or more posts that haven't
// been loaded yet.
$items.each(function() {
$items.each(function(this: HTMLElement) {
const $this = $(this);
const top = $this.offset().top;
const height = $this.outerHeight(true);
@ -228,6 +229,8 @@ export default class PostStreamScrubber extends Component {
// scrollbar's current period to a formatted version of this time.
const time = $this.data('time');
if (time) period = time;
return true;
});
this.index = index;
@ -269,7 +272,7 @@ export default class PostStreamScrubber extends Component {
this.$('.Scrubber-handle')
.css('cursor', 'move')
.on('mousedown touchstart', this.onmousedown.bind(this))
.on('mousedown touchstart', this.onmousedown.bind(this) as ZeptoEventHandler)
// Exempt the scrollbar handle from the 'jump to' click event.
.click(e => e.stopPropagation());
@ -279,7 +282,7 @@ export default class PostStreamScrubber extends Component {
// some event handlers. These handlers will move the scrollbar/stream-
// content as appropriate.
$(document)
.on('mousemove touchmove', (this.handlers.onmousemove = this.onmousemove.bind(this)))
.on('mousemove touchmove', (this.handlers.onmousemove = this.onmousemove.bind(this) as ZeptoEventHandler))
.on('mouseup touchend', (this.handlers.onmouseup = this.onmouseup.bind(this)));
}
@ -310,7 +313,7 @@ export default class PostStreamScrubber extends Component {
$scrubber.find('.Scrubber-description').text(this.description);
$scrubber.toggleClass('disabled', this.disabled());
const heights = {};
const heights: { before?: number; handle?: number; after?: number } = {};
heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible);
heights.after = 100 - heights.before - heights.handle;

View File

@ -32,7 +32,7 @@ export default class Search extends Component {
/**
* An array of SearchSources.
*/
sources: SearchSource[] = null;
sources?: SearchSource[];
/**
* The number of sources that are still loading results.
@ -50,11 +50,11 @@ export default class Search extends Component {
* around as new results load), but otherwise it will be numeric (the
* sequential position within the list).
*/
index: string | number = 0;
index: number = 0;
navigator: KeyboardNavigatable;
navigator: KeyboardNavigatable = new KeyboardNavigatable();
searchTimeout: number;
searchTimeout?: number;
view() {
const currentSearch = this.getCurrentSearch();
@ -124,14 +124,12 @@ export default class Search extends Component {
.on('click', () => this.$('input').blur())
// Whenever the mouse is hovered over a search result, highlight it.
.on('mouseenter', '> li:not(.Dropdown-header)', function() {
.on('mouseenter', '> li:not(.Dropdown-header)', function(this: HTMLElement) {
search.setIndex(search.selectableItems().index(this));
});
const $input = this.$('input');
this.navigator = new KeyboardNavigatable();
this.navigator
.onUp(() => this.setIndex(this.getCurrentNumericIndex() - 1, true))
.onDown(() => this.setIndex(this.getCurrentNumericIndex() + 1, true))
@ -150,7 +148,7 @@ export default class Search extends Component {
search.searchTimeout = setTimeout(() => {
if (search.searched.indexOf(query) !== -1) return;
if (query.length >= 3) {
if (query.length >= 3 && search.sources) {
search.sources.map(source => {
if (!source.search) return;
@ -168,7 +166,7 @@ export default class Search extends Component {
}, 250);
})
.on('focus', function() {
.on('focus', function(this: HTMLElement) {
$(this)
.one('mouseup', e => e.preventDefault())
.select();
@ -177,10 +175,8 @@ export default class Search extends Component {
/**
* Get the active search in the app's current controller.
*
* @return {String}
*/
getCurrentSearch() {
getCurrentSearch(): string | false {
return app.current && typeof app.current.searching === 'function' && app.current.searching();
}
@ -233,8 +229,6 @@ export default class Search extends Component {
/**
* Get all of the search result items that are selectable.
*
* @return {jQuery}
*/
selectableItems() {
return this.$('.Search-results > li:not(.Dropdown-header)');
@ -242,20 +236,15 @@ export default class Search extends Component {
/**
* Get the position of the currently selected search result item.
*
* @return {Integer}
*/
getCurrentNumericIndex() {
getCurrentNumericIndex(): number {
return this.selectableItems().index(this.getItem(this.index));
}
/**
* Get the <li> in the search results with the given index (numeric or named).
*
* @param {String} index
* @return {DOMElement}
*/
getItem(index) {
getItem(index: number): ZeptoCollection {
const $items = this.selectableItems();
let $item = $items.filter(`[data-index="${index}"]`);
@ -290,7 +279,7 @@ export default class Search extends Component {
.eq(fixedIndex)
.addClass('active');
this.index = $item.attr('data-index') || fixedIndex;
this.index = Number($item.attr('data-index') || fixedIndex);
if (scrollToItem) {
const dropdownScroll = $dropdown.scrollTop();
@ -307,7 +296,7 @@ export default class Search extends Component {
}
if (typeof scrollTop !== 'undefined') {
$dropdown.animate({ scrollTop }, 100);
$dropdown.animateScrollTop(scrollTop, 100);
}
}
}

View File

@ -1,7 +1,7 @@
export interface StackItem {
name: string;
title: string;
url?: string;
title?: string;
url: string;
}
/**
@ -38,9 +38,9 @@ export default class History {
/**
* Push an item to the top of the stack.
*
* @param {String} name The name of the route.
* @param {String} title The title of the route.
* @param {String} [url] The URL of the route. The current URL will be used if
* @param name The name of the route.
* @param title The title of the route.
* @param [url] The URL of the route. The current URL will be used if
* not provided.
*/
push(name: string, title?: string, url: string = m.route.get()) {