2016-11-16 19:45:10 +00:00
|
|
|
( function ( mw, $ ) {
|
2016-11-08 19:42:21 +00:00
|
|
|
|
2016-11-10 18:02:29 +00:00
|
|
|
var actions = {},
|
|
|
|
types = {
|
|
|
|
BOOT: 'BOOT',
|
|
|
|
LINK_DWELL: 'LINK_DWELL',
|
2016-11-28 12:00:07 +00:00
|
|
|
LINK_ABANDON_START: 'LINK_ABANDON_START',
|
|
|
|
LINK_ABANDON_END: 'LINK_ABANDON_END',
|
2016-11-10 18:02:29 +00:00
|
|
|
LINK_CLICK: 'LINK_CLICK',
|
|
|
|
FETCH_START: 'FETCH_START',
|
|
|
|
FETCH_END: 'FETCH_END',
|
|
|
|
FETCH_FAILED: 'FETCH_FAILED',
|
2016-11-28 12:00:07 +00:00
|
|
|
PREVIEW_DWELL: 'PREVIEW_DWELL',
|
|
|
|
PREVIEW_ABANDON_START: 'PREVIEW_ABANDON_START',
|
|
|
|
PREVIEW_ABANDON_END: 'PREVIEW_ABANDON_END',
|
2016-11-10 18:02:29 +00:00
|
|
|
PREVIEW_ANIMATING: 'PREVIEW_ANIMATING',
|
|
|
|
PREVIEW_INTERACTIVE: 'PREVIEW_INTERACTIVE',
|
|
|
|
PREVIEW_CLICK: 'PREVIEW_CLICK',
|
|
|
|
COG_CLICK: 'COG_CLICK',
|
|
|
|
SETTINGS_DIALOG_RENDERED: 'SETTINGS_DIALOG_RENDERED',
|
|
|
|
SETTINGS_DIALOG_CLOSED: 'SETTINGS_DIALOG_CLOSED'
|
2016-11-16 19:45:10 +00:00
|
|
|
},
|
2016-11-28 12:00:07 +00:00
|
|
|
FETCH_START_DELAY = 500, // ms.
|
|
|
|
ABANDON_END_DELAY = 300; // ms.
|
2016-11-08 19:42:21 +00:00
|
|
|
|
|
|
|
/**
|
2016-11-17 21:53:21 +00:00
|
|
|
* Represents Page Previews booting.
|
2016-11-14 19:37:11 +00:00
|
|
|
*
|
|
|
|
* When a Redux store is created, the `@@INIT` action is immediately
|
|
|
|
* dispatched to it. To avoid overriding the term, we refer to booting rather
|
|
|
|
* than initializing.
|
|
|
|
*
|
2016-11-17 21:53:21 +00:00
|
|
|
* Page Previews persists critical pieces of information to local storage.
|
|
|
|
* Since reading from and writing to local storage are synchronous, Page
|
2016-11-14 19:37:11 +00:00
|
|
|
* Previews is booted when the browser is idle (using
|
|
|
|
* [`mw.requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback))
|
|
|
|
* so as not to impact latency-critical events.
|
|
|
|
*
|
2016-11-08 19:42:21 +00:00
|
|
|
* @param {Function} isUserInCondition See `mw.popups.createExperiment`
|
2016-11-14 19:37:11 +00:00
|
|
|
* @param {String} sessionToken
|
|
|
|
* @param {Function} generateToken
|
2016-11-08 19:42:21 +00:00
|
|
|
*/
|
2016-11-14 19:37:11 +00:00
|
|
|
actions.boot = function ( isUserInCondition, sessionToken, generateToken ) {
|
2016-11-08 19:42:21 +00:00
|
|
|
return {
|
2016-11-10 18:02:29 +00:00
|
|
|
type: types.BOOT,
|
2016-11-14 19:37:11 +00:00
|
|
|
isUserInCondition: isUserInCondition(),
|
|
|
|
sessionToken: sessionToken,
|
|
|
|
pageToken: generateToken()
|
2016-11-08 19:42:21 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-16 19:45:10 +00:00
|
|
|
/**
|
|
|
|
* Represents Page Previews fetching data via the [gateway](./gateway.js).
|
|
|
|
*
|
|
|
|
* @param {ext.popups.Gateway} gateway
|
2016-11-25 12:42:02 +00:00
|
|
|
* @param {Element} el
|
2016-11-16 19:45:10 +00:00
|
|
|
* @return {Redux.Thunk}
|
|
|
|
*/
|
2016-11-25 12:42:02 +00:00
|
|
|
function fetch( gateway, el ) {
|
|
|
|
var title = $( el ).data( 'page-previews-title' );
|
|
|
|
|
2016-11-16 19:45:10 +00:00
|
|
|
return function ( dispatch ) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.FETCH_START,
|
2016-11-25 12:42:02 +00:00
|
|
|
el: el,
|
2016-11-16 19:45:10 +00:00
|
|
|
title: title
|
|
|
|
} );
|
|
|
|
|
|
|
|
gateway( title )
|
|
|
|
.fail( function () {
|
|
|
|
dispatch( {
|
2016-11-25 12:42:02 +00:00
|
|
|
type: types.FETCH_FAILED,
|
|
|
|
el: el
|
2016-11-16 19:45:10 +00:00
|
|
|
} );
|
|
|
|
} )
|
|
|
|
.done( function ( result ) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.FETCH_END,
|
2016-11-25 12:42:02 +00:00
|
|
|
el: el,
|
2016-11-16 19:45:10 +00:00
|
|
|
result: result
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-11-09 11:57:24 +00:00
|
|
|
/**
|
|
|
|
* Represents the user dwelling on a link, either by hovering over it with
|
|
|
|
* their mouse or by focussing it using their keyboard or an assistive device.
|
|
|
|
*
|
2016-11-16 19:45:10 +00:00
|
|
|
* @param {Element} el
|
2016-11-21 11:08:06 +00:00
|
|
|
* @param {Event} event
|
|
|
|
* @param {ext.popups.Gateway} gateway
|
2016-11-16 19:45:10 +00:00
|
|
|
* @return {Redux.Thunk}
|
2016-11-09 11:57:24 +00:00
|
|
|
*/
|
2016-11-21 11:08:06 +00:00
|
|
|
actions.linkDwell = function ( el, event, gateway ) {
|
2016-11-16 19:45:10 +00:00
|
|
|
return function ( dispatch, getState ) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.LINK_DWELL,
|
2016-11-21 11:08:06 +00:00
|
|
|
el: el,
|
|
|
|
event: event,
|
|
|
|
interactionStarted: mw.now()
|
2016-11-16 19:45:10 +00:00
|
|
|
} );
|
|
|
|
|
2016-11-25 10:40:33 +00:00
|
|
|
mw.popups.wait( FETCH_START_DELAY )
|
|
|
|
.then( function () {
|
2016-11-25 21:22:09 +00:00
|
|
|
var previewState = getState().preview;
|
|
|
|
|
|
|
|
if ( previewState.enabled && previewState.activeLink === el ) {
|
2016-11-25 12:42:02 +00:00
|
|
|
dispatch( fetch( gateway, el ) );
|
2016-11-25 10:40:33 +00:00
|
|
|
}
|
|
|
|
} );
|
2016-11-09 11:57:24 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user abandoning a link, either by moving their mouse away
|
|
|
|
* from it or by shifting focus to another UI element using their keyboard or
|
|
|
|
* an assistive device.
|
|
|
|
*
|
2016-11-16 19:45:10 +00:00
|
|
|
* @param {Element} el
|
2016-11-09 11:57:24 +00:00
|
|
|
* @return {Object}
|
|
|
|
*/
|
2016-11-16 19:45:10 +00:00
|
|
|
actions.linkAbandon = function ( el ) {
|
2016-11-28 12:00:07 +00:00
|
|
|
return function ( dispatch ) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.LINK_ABANDON_START,
|
|
|
|
el: el
|
|
|
|
} );
|
|
|
|
|
|
|
|
mw.popups.wait( ABANDON_END_DELAY )
|
|
|
|
.then( function () {
|
|
|
|
dispatch( {
|
|
|
|
type: types.LINK_ABANDON_END,
|
|
|
|
el: el
|
|
|
|
} );
|
|
|
|
} );
|
2016-11-09 11:57:24 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-10 12:05:38 +00:00
|
|
|
/**
|
|
|
|
* Represents the user clicking on a link with their mouse, keyboard, or an
|
|
|
|
* assistive device.
|
|
|
|
*
|
2016-11-16 19:45:10 +00:00
|
|
|
* @param {Element} el
|
2016-11-10 12:05:38 +00:00
|
|
|
* @return {Object}
|
|
|
|
*/
|
2016-11-16 19:45:10 +00:00
|
|
|
actions.linkClick = function ( el ) {
|
2016-11-10 12:05:38 +00:00
|
|
|
return {
|
|
|
|
type: 'LINK_CLICK',
|
2016-11-16 19:45:10 +00:00
|
|
|
el: el
|
2016-11-10 12:05:38 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-28 12:00:07 +00:00
|
|
|
/**
|
|
|
|
* Represents the user dwelling on a preivew with their mouse.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
|
|
|
actions.previewDwell = function () {
|
|
|
|
return {
|
|
|
|
type: types.PREVIEW_DWELL
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents the user abandoning a preview by moving their mouse away from
|
|
|
|
* it.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
|
|
|
actions.previewAbandon = function () {
|
|
|
|
return function ( dispatch ) {
|
|
|
|
dispatch( {
|
|
|
|
type: types.PREVIEW_ABANDON_START
|
|
|
|
} );
|
|
|
|
|
|
|
|
mw.popups.wait( ABANDON_END_DELAY )
|
|
|
|
.then( function () {
|
|
|
|
dispatch( {
|
|
|
|
type: types.PREVIEW_ABANDON_END
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-15 18:18:13 +00:00
|
|
|
/**
|
|
|
|
* Represents the user clicking either the "Enable previews" footer menu link,
|
|
|
|
* or the "cog" icon that's present on each preview.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
|
|
|
actions.showSettings = function () {
|
|
|
|
return {
|
|
|
|
type: 'COG_CLICK'
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-14 19:37:11 +00:00
|
|
|
mw.popups.actions = actions;
|
|
|
|
mw.popups.actionTypes = types;
|
2016-11-09 11:57:24 +00:00
|
|
|
|
2016-11-16 19:45:10 +00:00
|
|
|
}( mediaWiki, jQuery ) );
|