I6d9ff52b introduced a regression where if a logged out user clicks the
settings cog then an error is thrown.
For now, passing the event to the behavior for further processing is
required. However, it's clear that this makes the
ext.Popups.PreviewBehavior abstraction leaky.
Bug: T162324
Change-Id: I9dea04eb7435f9349e60d477f5701ec5dd655ebd
We have to be careful about the namespaces here, and then we don't
need the awful `.html( .html() )` hack. (I honestly have no idea
why that even worked for some browsers, it really shouldn't have.
The comment next to it is wrong.)
* Construct the 'svg:svg' element with the right namespace
* Set 'xlink:href' attribute on 'svg:image' element with the right namespace
Doing this correctly makes the thumbnails work in Opera 12, and it also
works as before in (at least) Chromium 57, Firefox 53, IE 11 and Edge.
I can't find out what version of Safari the other hack here was
supposed to apply to, but the code was wrong in both cases, and the
hack was mistakenly also applied to modern Chromium.
Useful resources for dealing with SVG embedded in HTML while scripting:
* http://stackoverflow.com/questions/6701705/programmatically-creating-an-svg-image-element-with-javascript
* http://jsfiddle.net/UVFBj/8/
* https://www.w3.org/Graphics/SVG/WG/wiki/Href#xlink:href
Bug: T161799
Change-Id: I30b2a1291811296424018e013bd07055ae7551d7
Require that two promises are resolved (or one is rejected) before the
FETCH_COMPLETE action is dispatched. The first promise represents the
gateway request and the second represents an arbitrarily long delay. If
the first resolves before the second, then there'll be a delay until the
second resolves; whereas if the first rejects, then there's no delay.
Change-Id: I496fe317337745c593594efff26688c46d661bf3
Mixing in the delay was introduced in If3f1a06f so that the total RTT
for an API request could be calculated. Now that the FETCH_END action is
dispatched when the gateway request ends and not when the preview model
is resolved, this additional information (state) is redundant.
Change-Id: I7e6ffe0945ffedd9425525fa7da855e729d50b77
Ideally, the preview model is resolved after 500 ms, regardless of
whether the internal gateway takes 100 or 300 ms. Given this, there's an
important distinction to be made between the "fetch" ending and it
completing and their associated actions.
Changes:
* Dispatch the FETCH_COMPLETE action when the preview model is resolved.
* Update the reducers accordingly.
Change-Id: I62c9cb0430284b76338ea80bd170cac5af4be9d0
If the user has disabled PP via the settings dialog or they aren't in
the experimental condition, then link titles shouldn't be emptied.
Because this behavior has to respond to the user enabling/disabling PP
within the same page session, change the linkTitle change listener
rather than conditionally registering it.
Bug: T161277
Change-Id: I53c1a1d3e4436e2ffe08da27da388f394f4e8817
Binding the behavior to the preview before it's shown means that the
application will respond to user interactions with the preview even
though it's transparent.
This fixes scenario 4 from T159490.
Bug: T159490
Change-Id: Ia2d06869868d07af60bdeb49d46612a4a0dc02e9
If the user abandons link A (or preview A) and immediately dwells on
link B, then log a "dismissed" or "dwelledButAbandoned" event.
In this context, "immediately" means before the ABANDON_END action is
dispatched, which, currently, is 300 ms after the ABANDON_START action
is dispatched.
Bug: T159490
Change-Id: I49f0f5dfb3e6c08844f1794fee8cb6170e93981b
Reducer changes:
* Add tests for ABANDON_END case.
* Extract the body of the ABANDON_END case into the createAbandonEvent
helper function.
Additional changes:
* totalInteractionProperty -> totalInteractionTime elsewhere in the same
file.
Bug: T159490
Change-Id: Ifff34271395f330b83cfe487e84800fe2d6f3811
Reducer changes:
* Make the eventLogging reducer queue a "tapped settings cog" event when
reducing the SETTINGS_SHOW action.
This was discovered while testing I6ce7d72b.
Bug: T159490
Change-Id: I6ce7d72b364d20c71b0e2cfed98e99f7997895e5
Like dwelling and abandoning, clicking on a preview is the same as
clicking on a link.
This fixes scenario 3 from T159490.
Bug: T159490
Change-Id: I6d9ff52b62bec93ebfcc9b6d267a46cf961852fb
For now, mirror the interaction modelling in the preview reducer in the
eventLogging reducer to handle the user either:
* Repeatedly dwelling on and abandoning a link.
* (Repeatedly) moving their mouse between the link and the preview.
This fixes scenarios 1, 2, 5, and the general issue from T159490.
Bug: T159490
Change-Id: Ia771f325e541c107348b16b47c5b786c97847652
Step 1 of T161284. Given that the median API response time (as measured
by the client) is ~115 ms [0] and the API response is artificially
delayed so that the preview starts fading in at 500 ms, we can increase
the API request delay to 150 ms without affecting the current UX while
decreasing the number of incidental HTTP requests triggered by the user
glancing their mouse over a link to another page.
[0] https://grafana.wikimedia.org/dashboard/db/reading-web-page-previews
Bug: T161284
Change-Id: I4c4a766467cdb4cd47c4231c1106c35bab67855e
When EventLogging is unavailable do not initialise the EL-related code
or try to send any events.
When EL is enabled for a brand new user we request an additional module
during boot causing an additional HTTP request. Page Previews continues
to boot normally regardless of whether the request fails.
This approach doesn't impact boot or first paint time. Once the module
is loaded once it should be cached locally, subject to the
ResourceLoader's policy. Moreover, the RL will not attempt to load the
module twice so this doesn't impact the performance of other modules.
Bug: T158999
Change-Id: I7ed7f00d52279151ece23e5aced4f2adb0f7fdc3
... container.
I19e67ae4 hide the overflowing parts of the SVG image element in IE9-11
for a number of cases but not all of them, e.g. see T139297#3089714.
Moving the overflow: hidden property to the SVG element fixes the above
case and is clearer.
Tested in IE9-11 on Windows 7, and Chrome (56.0.2924.87) on macOS Sierra
(10.12.3).
Bug: T139297
Change-Id: I9c397d7333766b40abbf14b6ade96788f5023dfa
Changes:
- remove focus events listeners as they are triggered after switching tabs
- show PagePreview on keyup event
Bug: T158631
Change-Id: I7533f896604e0e0a8ea6e900ae4f7d12b6458836
IE doesn't appear to update/redraw the SVG image element when Setting
its clip-path attribute to '', not removing it. This is problematic as
the attribute is always set to a default value (in the createThumbnail
function) before the preview is laid out.
Bug: T160237
Change-Id: I4559ff5018b8f4ecf06f6f5d9462a999d9726b94
For logging to work:
1. $wgWMEStatsdBaseUri needs to point to a valid statsv endpoint,
e.g. 'https://en.wikipedia.org/beacon/statsv'.
2. $wgPopupsStatsvSamplingRate needs to be set. Note that the codebase
already contains the EventLogging functionality, which is configured
separately. Separately configuring different logging mechanisms
allows us to avoid sampling mistakes that may arise while choosing
one or the other. For example, let's say we want to use EventLogging for
10% of users and statsv for 5%. We'd sample all users into two
buckets: 50/50. And then we'd have to set the sampling rates as
20% and 10% respectively, only because of the bucketing above. To avoid
this kind of complications, separate sampling rates are used for each
logging mechanism. This, of course, may result in situations where a
session is logged via both EventLogging and statsv.
3. The WikimediaEvents extension needs to be installed. The extension
adds the `ext.wikimediaEvents` module to the output page. The
logging functionality is delegated to this module.
Notable changes:
* The FETCH_START and FETCH_END actions are converted to a timed action.
* The experiments stub used in tests has been extracted to the stubs
file.
Logged data is visualized at
https://grafana.wikimedia.org/dashboard/db/reading-web-page-previews
Bug: T157111
Change-Id: If3f1a06f1f623e8e625b6c30a48b7f5aa9de24db
... thumbnails.
A good example of the difference in behaviour of the PageImages API is
here <T156800#3087507>. The API defers to File#transform, which scales
the largest dimension of an image, not always the width, e.g. if an
image is 1000px x 2000px and the request is for a thumbnail "of 1800px",
then the thumbnail will be 900px x 1800px.
Bug: T156800
Change-Id: I64bc2244ee78a594298d8637233b0da1083700eb
Keep all configuration-like values in one file.
Changes:
- moved EXTRACT_LENGTH to constants.js file
Change-Id: Ibe5ecfc60f2c09a30a9ecb3586bc5fb6a7365476
Webpack 1.14.0 is an old version, switch to using latest stable which
has better documentation, tree shaking, ES2015 modules and a core team
of contributors with funding. See https://webpack.js.org/
Additional changes:
* Recompile the frontend assets
Change-Id: I2c5940276e99dee104d04c6a0b83d8ab36a99df5
If the image isn't an SVG then it shouldn't be scaled past its original
dimensions. Handle the case where the requested thumbnail can't be
generated on the server as the original is too small ( < 320px,
currently [0]) in the same way.
Moreover, if the image happens to have the exact dimensions that we're
requesting (300px or 600px wide, currently [1]), then use the original
image to avoid unnecessary work/pressure on caches.
Supporting changes:
* Update the SVG_RESTBASE_RESPONSE fixture to use the extension returned
by RESTBase (and the PageImages extension) for the thumbnail:
.svg.png.
[0] https://github.com/wikimedia/restbase/blob/master/v1/summary.yaml#L121
[1] https://github.com/wikimedia/mediawiki-extensions-Popups/blob/master/src/constants.js#L2
Bug: T156800
Change-Id: I5d0aa161e80869e4b4f5425d906d1e753047a3a3
Instead of importing the modules from sources (which you should do if
you properly define NODE_ENV and use uglifyjs from webpack) import the
already compiled files on the npm packages.
This results in 5kb less on the compiled bundle.
Change-Id: I83732ea79a59b611c117ddcf4c262948c795f642
Following on from I19e67ae4, IE9-11's treatment of SVG elements that
overflow their containers means that the truncating pseudo-element and
the settings cog is occluded in a portrait-mode preview.
"Pad" the extract horizontally using a margin to force the SVG element
into the correct position.
Bug: T156800
Bug: T139297
Change-Id: I0da6af6d4cbcc69c6465b37714856e59199ae6e4
Unlike modern browsers, IE9-11 (at least) don't hide the overflowing
parts of an SVG image element. Make this explicit by adding the
overflow: hidden property to the preview's container element.
Bug: T156800
Bug: T139297
Change-Id: I19e67ae4584d90c02dc5a2dd1c8bdb5773cd2283
Now that most unit tests are run in node with common.js for loading
sources there is no reason to keep global variables around exposing all
the sources.
Only exception is the only qunit integration test processLinks.test.js
which still consumes mw.popups.processLinks, which is the only global
variable remaining in the codebase.
Changes:
* Remove references to mw.popups in code comments and reference the JS
file instead
* Remove popups.js which exposes all common.js modules as global
variables
* Export mw.popups.processLinks in processLinks.js for testing in
processLinks.test.js
Change-Id: I91066654b9282f73a80eb1ba5018bd091656c61d
We used to query the MediaWiki API to only return non-free images.
This patch allows us to query the API for images with any license.
The RESTBase end point is already returning images with any license.
Bug: T158632
Change-Id: I9ac60b6f74a7f7eb2cb160ee522c2c3a26dd0858
All the other masks use an 8px offset for the triangle. But this
specific mask used 250 - 243 = 7px offset.
Bug: T153840
Change-Id: Ib72842d18bd844ff37509cf5bf1dedd4e0f99dbc
Rather than manipulating the URL of the original image to get the URL of
the appropriately sized thumbnail, manipulate the URL of the thumbnail
image.
While we could manipulate either the thumbnail or original image URL,
there are subtle differences between the two, so manipulating the latter
makes the generateThumbnailData function as simple as possible, e.g. we
don't have to splice in "/thumb" after "/commons".
Also, ensure that the thumbnail's dimensions are scaled appropriately.
Bug: T156800
Change-Id: I6825bad14b1131dc81f23dcf120cf8ffb7d7b4f6
* Logged in users bypass bucketing. They keep working as before.
* When Page Previews is configured as a beta feature, logged out users
won't see the feature.
* If an anonymous user has enabled/disabled the feature using
the settings cog then they will see or not see the feature
depending on the value of their setting.
* The other anonymous users are bucketed. By default 90% of these
users see the feature, the other 10% don't. These numbers can be
controlled by the config variable `wgPopupsAnonsEnabledSamplingRate`.
Bug: T157700
Change-Id: I5307587b10f4849c4e82d3b064ff759121c2de67
mw.storage#get doesn't take a default value to return if the underlying
storage is disabled or the key is missing. In the former case it'll
return false and in the latter it'll return null, i.e. in neither case
will it return undefined.
Bug: T157700
Change-Id: I3f653c11468e17b64765e85ebb3b8f03e311352a
Because of the globals mw.popups.wait usage and mocking in both actions
and integration, they need to be migrated in a single step, fixing them
both to require wait.js and mock using mock-require instead of the
global variable.
Additional changes:
* Fix FIXMEs about actions.js using the global mw.popups.wait instead of
the require one.
* Fix the unit tests to use require mocking for wait.js instead of
global variable mocking in both integration and actions tests
* Change tests that use deferreds and promises to be async qunit tests
(Deferreds are asynchronous with jQuery in node, apparently they
weren't in the browser)
* Change integration.test.js to use require on Redux and ReduxThunk
Change-Id: I8e3e87b158bd11c9620e77d0a73e611cf9e82183
The "checkin" part of the Popups schema was superseded by the
ReadingDepth schema, the implementation of which is tracked by T155639.
As well as removing all checkin-related code, update the Popups schema
to the latest version - the version that doesn't have the checkin
property.
Bug: T155639
Depends-On: I762ec3fc91decf3cffa869dbd783faf62f01329a
Change-Id: If764917b6e121e1f9db980a4efa30c0f7a166197
CSSJanus v1.1.3 doesn't appear to flip the "to right" argument for the
linear-gradient CSS function. As with the position of the truncating
element in I0d50a8b5, the direction of the gradient doesn't vary with
the text direction of the current page but that of the target page.
Bug: T158858
Change-Id: I4b6fcf68bdf57722348513f12c7b19f80b2545c4
The render change listener is hard coupled to the renderer file, so in
order to migrate the test, instead of stubbing a global variable, we had
to either inject the renderer into the change listener factory as done
everywhere else, or mock the require call.
In order to do one thing per commit, we're mocking the require call
here to get the migration done, but added a FIXME to use dependency
injection instead in a future change.
Change-Id: I50f82cdc9664d34b8a8ccc1ff368f7209404159d
In index.js. Instead of using the global variable/object popups, require
things from their files so that we can remove the global variables when
we can run qunit tests with commonjs in node.
Change-Id: I85408f01eca27f97cf46b2076176fcc16c037829
This change resizes thumbnails to the appropriate width
based on the value of mw.popups.gateway.THUMBNAIL_SIZE
Tests cover
* When requested thumbnail is < than original size
* When requested thumbnail is > than original size
* When requested thumbnail is an svg and originalimage
smaller than requested thumb size
Bug: T156800
Change-Id: Ib375b97e2bc959e91de5177efc3df1f2ded54a5b
This way, src contains sources, and dist contains distribution files.
Also, add some documentation about the folders in the README and an adr.
Change-Id: Ie0b9f6475b8423b90e927633d883bde3cd5d5e4d
In order to automatically verify in CI that the built assets are up to
date with the commited sources, we need to keep the built assets in
a folder separate from the RL assets.
* Rename the compiled assets folder to industry standard `dist`
Change-Id: I8c5898f9bb29fee7164a7038b835a5f7efd33dbc
So that production code can be debugged properly. Independent source
maps files aren't loaded until the developer tools are open.
Change-Id: Ic8c3c10315d3a3be0f42505834005a3cab77d130
Until this appears in core it makes sense to package it up as
part of ext.popups resource loader module.
Version numbers from npm are pinned to exact versions to control the
upgrade path of the libraries instead of leaving it to semver on
developers machines.
Bug: T156333
Change-Id: I33368ecc3c8e911d96f846669bcd831c182749f2
boot.js is renamed to index.js and popups is now bundled
up inside popups.js
To support qunit tests, the library is still exposed as
mw.popups with a FIXME to remove later when it is no longer
necessary
Bug: T156333
Change-Id: Ieb6b4b0344af2701f99ef0fcc786d2378fd2fceb
Generate changeListeners via webpack
We now use a build folder to build the JavaScript for
our ResourceLoader modules. This is the first change
in a line of changes.
A source map is provided for debug support.
Bug: T156333
Change-Id: I771843d1ddb4b50adedc3fa53b30c2f1d8a76acb
Sometimes we make choices on the users behalf if we don't have
sufficient information, so this name is more applicable.
If beta features is disabled and the user is anon they have not
explicitly opted in.
Change-Id: I5d816f569fc54f8bf74d6e5a06246b7fa7036e06
* Create new namespace mw.popups.gateway to contain them
* Create folder resources/ext.popups/gateway/
* Split gateway{,.test}.js into gateway/{mediawiki,rest}{.test,}.js
* Extract stateless functions out of factory scope now that there are no
name collisions between the factories.
Bug: T123445
Change-Id: Ib256871c3e4cfe3f13361cb66d4e9a67e9823c7b
Instead of using constructor functions, use factory functions to
generate the gateway objects, because of:
* Consistency on the approach in the repository, no constructor
functions are used, the factory function pattern prevales.
* Real private data with closures
* No use of `this`, which is dynamic and unbound in JS and a source of
errors. In contrast, by using a factory function, the
function/methods-of-the-object are tightly bound to the internal data.
Additional changes:
* Specify more the type of createRESTBaseGateway's parameter to improve
clarity on the intent of the parameter
* From: @param {jQuery} api
* To: @param {Function} ajax function from jQuery for example
Supporting documentation:
* https://medium.com/javascript-scene/javascript-factory-functions-vs-constructor-functions-vs-classes-2f22ceddf33e
Change-Id: Iacbb098b646843a01f459b15343057e2e4851d35
Prepare to shift to a JS bundler by placing definitions at bottom
of page (these are currently assignments to mw.popups). In future
these are easily switched to module.exports line
Change-Id: Iaa5d78fee1cdb6fc572d2f1781f1d4fb59475e84
* Introduce the new config variable `PopupsAPIUseRESTBase`.
* Create a gateway interface that exposes the getPageSummary
method. Both MediaWiki API gateway and RESTBase gateway
implement this interface.
Bug: T123445
Change-Id: I71a8a848f3143fa4a0dfd4ca182ee086903110bc
Extract the getBaseData function from the eventLogging reducer so that
changes in the shape of the base data will be isolated to that function.
Additional changes:
* Clarify that the eventLogging reducer is specific to the Popups
schema. Add a TODO for revisiting the name, at least.
Bug: T156893
Change-Id: I99c102d3a1dbf77d526e5ab33e99929f351f5768
The existence of these files was causing me much confusion as I thought
they were still being used in the mpga branch.
If this is note the case they should be removed to make the repo easier
to understand.
Changes:
* Move the ext.popups.animation.less into ext.popups since that's where
its shipped.
* Remove files which are not being used.
* Since csslint now runs on ext.popups.animation.less fix the linting
issues (previously linting was not occuring)
Change-Id: Iae0a78d0b8a13353de70794b67387f2c3bab44c6
In I6bbff6a5 a preview was assigned the "extract" type if it had an
extract whereas it should've been assigned the "page" type.
Bug: T152004
Change-Id: I5e0cdc8f528647f1e20873753be29c6b85b3a384
Note this is a breaking change in the sense that it breaks the function
signature for createModel which no longer needs to be passed the last
modified time. Given this change is in the mpga branch at current time
and hasnt been exposed for public use I have deemed this okay.
The change removes tests relating to the last modified bar, removes
lines in the templates and updates existing tests and code to reflect
the new function signature for create model.
Settings icon is floated to right which will be flipped for RTL
users.
Bug: T137775
Change-Id: I7737e37d956c62f1f1c0694d7a25a58d91651f4d
* Load the close icon (previously was not loaded)
* Take opportunity to simplify selectors in setting panel and remove
unnecessary id selectors
* Correct size of header to be consistent with mediawiki ui icon
Note: there's a slight movement in the heading text's position
presumably due to inconsistiencies between the text
inside the Done/Save buttons
Bug: T154645
Change-Id: Icd978b45051c43f24ee1c9a8574a961b942082f1
The preview model is included in the FETCH_END action so, when reducing
that action, pluck the preview type from the model and add it to the
interaction state.
Change-Id: I0e51a85b4dada8f9a17ec4882e0c13b2c4382d24
Per T152004, if the preview has an empty extract, then it's a "generic"
preview; it's an "extract" preview otherwise.
Bug: T152004
Change-Id: I6bbff6a507fe3e4f03b3a44f64d875e7dbb512df
Following on from I20f29657, simplify the gateway by making it return
instances ofext.popups.PreviewModel.
Supporting changes:
* data -> model in mw.popups.renderer#render and the
create{,Empty}Preview helper functions.
Bug: T152004
Change-Id: I531f609056ae813ae5e6b1d53010d77be0799ec1
As noted in the review of I71a8a84, creating a new object to represent
the thumbnail is confusing. It's also somewhat wasteful.
Since both the MediaWiki API and RESTBase both agree on using "source"
as the key for the thumbnail's URL, it's reasonable to use it in the
gateway and renderer.
Bug: T152004
Change-Id: Ie1346d13b6e88004b817f5968448188ed83cfda4
After the gateway has made a request, it processes the page. This
processing both mangles and processes the MediaWiki API response. The
latter step contains two pieces of related business logic:
1. Deciding if a page has been modified recently.
2. Processing the extract/deciding if it's viable (see processExtract).
In order to support switching between the MediaWiki API and RESTBase and
to simplify the event logging reducer when it comes to instrumenting the
"type" of preview, extract this business logic into a model.
Bug: T152004
Change-Id: I20f29657fcf94101a71ed13c0920508db71292ce
I4c15296e introduced the wgPopupsConflictsWithNavPopupGadget client-side
config variable, an always-available flag that represents whether the
user has enabled the NavPopups gadget. This property has been missing
from the Popups instrumentation since I8a3f5835.
Changes:
* Add the value of wgPopupsConflictsWithNavPopupGadget to BOOT action
and reduce it into the base instrumentation data.
Bug: T151058
Change-Id: I09924d0cb10e96b0a846940506ebfeaa7086cd17
Ieb00709e changed the names of the page content language related
variables returned by the API from langdir and langcode to
languageDirection and languageCode respectively without updating the
renderer.
Moreover, the extract truncation mechanism introduced in I2ec0c04
couldn't handle RTL languages.
Both of these issues were found while writing a test plan for Page
Previews.
Change-Id: Ied3dbd7cf82749198e792a2f9d2241582aeff25c
Since the footer link part of the settings system - clicking the link
opens the settings modal - it seems appropriate that it should be
controlled by state managed by the settings reducer.
Bug: T146889
Change-Id: I3a8549dbf1952cd0556f663496c55de91acaf2c0
As before, we need to send the Page Previews blob that logged out users
can enable/disable previews.
Changes:
* Unconditionally add the ext.popups RL module to the output.
* Send the value of Popups\PopupsContext#isEnabledByUser to the client
as $wgPopupsIsEnabledByUser.
* Make mw.popups#isEnabled return $wgPopupsIsEnabledByUser if the user
is logged in.
Bug: T146889
Change-Id: Id2ccfaa81a327e222fff400f4a5f22f96c99ea31
The behavior of the cog varies when:
* The user is logged in/out.
* Page Previews is enabled as a beta feature.
Since the behavior of the cog doesn't vary per-preview, it can be
determined at boot time and passed to the renderer. However, in order to
keep the renderer stateless, we pass the behavior to it when a preview
is added to the DOM.
Changes:
* Add the mw.popups.createPreviewBehavior factory function, which
returns an object that encapsulates how a preview responds to the user
dwelling on it, abandoning it, and clicking on the cog.
* Invoke mw.popups.createPreviewBehavior at boot time and pass it to the
mw.popups.changeListeners.render change listener, which then passes it
to mw.popups.Preview#show.
* Make mw.popups.Preview#show responsible for binding event handlers
and configuring the cog based on the behavior.
Bug: T146889
Change-Id: I39d7d0afd7b1fe896019a1b3a82ee907bfb20edd
The SchemaPopupsSamplingRate config variable is inconsistently named and
even forwarded to the client as wgPopupsSchemaPopupsSamplingRate.
Changes:
* SchemaPopupsSamplingRate -> PopupsSchemaSamplingRate
* Forward PopupsSchemaSamplingRate to the client as
$wgPopupsSchemaSamplingRate.
Bug: T146889
Bug: T146434
Change-Id: I80d6a0abccf462e2eb0fd96af6849b5e82b49c26
Per Id1339dc2, the LINK_ABANDON_* and PREVIEW_ABANDON_* actions can (and
should) be merged, as they are always reduced in the same way.
Change-Id: I71b30d4d2774deb4efea9e565f2ccd7383bf08c1
Initially, the link element was added to LINK_ABANDON_* to determine
when an interaction should be reset. However, this wasn't enough to
protect against timing-related bugs, e.g. T154923. Now that tokens are
used to determine when interactions should be reset, the link element
can safely be removed from the LINK_ABANON_* actions.
Supporting changes:
* Update the return type of mw.popups.actions.linkAbandon in its
DocBlock.
Change-Id: Iaaed7a4846af75f9c4051d7bc761022ea5b3f6cf
I2ecf575b introduced a regression where the linkTitleChangeListener
wouldn't destroy the active link's title if it had been dwelled on
within 300 ms of the previous active link being abandoned.
The LINK_ABANDON_END action is dispatched after 300 ms and ignored if
the active link has changed.
Change-Id: If0c16afd6ca1c44f0e7eed497f62f0190005a619
... instead of using the active elements, and check also the user
dwelling flag to only act if the user is not dwelling.
Preview and link abandon end and start share now test cases, meaning it
can be collapsed into one action creator in a followup commit.
Change-Id: Id1339dc23e8f1b1b7514c769cd09f8bdadc759b4
When dwelling back to a link, previously a new LINK_DWELL action would
be sent and the reducer would reset the interaction as if it was a new
one.
This shouldn't happen, since dwelling back to the active link (from
the preview, for example) is not a new interaction, and should not
create a new interaction or hide and show the preview.
With this change, the preview reducer has the notion of new or repeat
interactions, and only resets state on new ones, and only sets
isUserDwelling when dwelling on a the link of the current interaction.
Also when the interaction is repeat, we guard on the action creator and
don't trigger the wait or the fetch request.
Change-Id: I71cde81cbfe50b6f955e562e7e5b57d0f920fdb9
... after dwelling on preview.
Currently, the asynchronous PREVIEW_ABANDON_END action wouldn't be
ignored if the user were to have dwelled on the link that the preview is
about. The action is only ignored if the user is dwelling on the
preview, i.e. if preview.isUserDwelling is truthy.
Set preview.isUserDwelling to truthy if the user is dwelling either on
the link or on the preview.
Bug: T154923
Change-Id: I8e6989790da5884992ee9dda9e4895e2e58e6694
Consider the user repeatedly dwelling on and abandoning a link. Testing
whether or not the element has changed before modifying state is not
sufficient. Fortunately, we already generate a unique token and include
it in the LINK_DWELL action for use in the eventLogging reducer - the
so-called "interaction token".
Change-Id: Iae9544055f7eccb4f7f071797eb360bc3456861a
* To speed the time the tests spend running
* To make them reliably execute and not depend on magic numbers
Additional changes:
* Use mw.now instead of Date on checkin.js
* Split big setVisibleTimeout test into several smaller ones
* Extract helpers for the tests
Change-Id: I9d3233fccf6de0997f968d096e375df996e87786
After the preview fade out animation has completed, then the preview
element should be removed from the DOM as it'll never be used again.
Supporting changes:
* Add the preview element to the DOM in ext.popups.Preview#show so that
it mirrors removing it from the DOM in #hide.
Change-Id: I6b3adc962aa13fbd46dce5f4c4f741299e43c6d9
While I1bf953b2 fixed the typo in FETCH_START_DELAY, it didn't do
anything to address the inconsistency in the time it takes to render a
preview (preview delay).
If the gateway result resolves before the target preview delay (500 ms)
is met, then delay dispatching the FETCH_END action until it is. If,
however, the gateway result resolves after the target preview delay,
then dispatch the FETCH_END action immediately.
Supporting changes:
* Expose the fetch action to ease testing it and to help tidy up the
mw.popups.actions.linkDwell tests.
Change-Id: Idf02343a0417cfbb33093a81d97ecebc5c1c7379
Use schema revision 16163887.
Add the 'checkin' action, which is accompanied by the 'checkin'
property. The action is logged at the following seconds
(Fibonacci numbers) after the page loads: 1, 2, 3, 5, 8, 13, 21,
34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765.
The `checkin` property contains the values listed above.
Bug: T147314
Change-Id: Ib9ec7bd0e60aa34a04e32222b025347f6ee31794
...with the wikimedia presets.
For automatically fixing most of the JS lint problems run
grunt eslint:fix
Some rules of stylelint were disabled given they cause problems with
existing popups code (like no id selectors for example).
Change-Id: I2153047c3ddbea50572dd329989088bb20787515
Action changes:
* Update the BOOT action to include isEnabled and update the associated
tests.
Reducer changes:
* Make the preview and eventLogging reducers handle the BOOT action's
new shape.
Bug: T152687
Change-Id: I3fa2098269a32912eda99ceb8f13887688a14c15
The Page Previews A/B test was disabled in T144490. After the changes
for that task had been deployed we discovered that the old definition
for when previews are enabled was invalid.
Previews are enabled:
* If the beta feature is enabled and the user has enabled the beta
feature.
* The user hasn't disabled previews via the settings modal.
* And soon, if the beta feature is disabled and the user hasn't disabled
previews via their user preferences (see T146889).
Changes:
* mw.popups#createExperiment -> mw.popups#isEnabled
* Make mw.popups#isEnabled act like a factory to maintain backwards
compatibility.
* Update the associated tests.
Bug: T152687
Change-Id: I713a90dfb29866b27738e7d19e8a22518a12d417
When opening the settings dialog, the form didn't represent the current
enabled status of the application. This change makes sure that every
time the form is shown, the form state represents the current
application state.
If the application is enabled, then the 'simple' (Enabled) option is
selected on the form. If it is disabled then if there's Navigation
popups, it selects 'advanced' (Advanced popups), if there are not, it
selects 'off' (Disabled).
Changes:
* Change listeners
* Set the form state every time the form is going to be shown
* Update tests
* Supporting changes
* Add settingsDialog#setEnabled which updates the DOM form based on the
enabled flag and the navpops state
* Extract isNavPopupsEnabled function in settingsDialog.js to be used in the
form creation and also when setting the form enabled state
* Add test verifying changeListeners#settings shows and sets enabled state
properly when showing the dialog more than one time
Change-Id: Ic660f48d9a78e47c09a192ab86681196d2e01d61
Changes:
* Generalized previewCount change listener to syncUserSettings
* Added state.preview.enabled to be saved on change
Change-Id: I403a490fee9c8e125175996ba30c63c232b5598b
The save action has been implemented, and it is listened to by the
canonical enabled state in the previews reducer, and by the settings
reducer to perform UI changes.
The enabled state of the application has been kept in the preview
reducer as the canonical source of truth. See supporting changes for
documentation about the decision.
Actions:
* Introduce new action SETTINGS_CHANGE with the enabled status
* Trigger that action when clicking Save in the settings dialog
Reducers:
* Listen to SETTINGS_CHANGE in the preview reducer to update enabled
status
* On the settings reducer
* Handle the SETTINGS_CHANGE action
* Add showHelp flag to determine if the help should be showing
Change listeners:
* Switch to compare past vs present changes in the implementation
* Handle showing and hiding the help
Supporting changes:
* On the rendered settings dialog:
* Change #hide to actually just hide and remove legacy if statement
* Add #toggleHelp method to show or hide the help dialog
* Add doc/adr/0003-keep-enabled-state-only-in-preview-reducer.md to
support the decision of making the saveSettings action creator return
a Redux.Thunk and keeping the enabled state just in the preview
reducer.
* Add NB to actions#saveSettings explaining and linking to the
document
Follow commits soon:
* Persist the settings change to local storage when it changes, and
unify with the preview change listener
Change-Id: I80dc5f29fbe6286f2e3e3b50d909894bc5041ccd
Reducer changes:
* Break the mw.popups.reducers.rootReducer test into @@INIT tests
for each reducer as there's shouldn't be any need to test that a
framework works as documented.
Changes:
* Move the mw.popups.reducers#preview, #eventLogging, and #settings
reducers into their own files in resources/ext.popups/reducers/.
* Make the associated tests mirror the new layout.
* Move the initialization of the mw.popups.reducers namespace into its
own file.
* Remove the mw.popups.rootReducer property in favour of a simple
private factory function per the reducer change above.
Change-Id: I94229d9ef1985f3806eec44c2e8234a5bbddc94f
Now when on a hovercard and clicking the cog, it should show the hovercards
settings menu.
Additional changes:
* Change the changeListener/settings to create and attach the DOM element
just once to the DOM
Change-Id: Id685ddcda9532528fc62b383539788f785089ef0
* Port ext.popups.desktop/ext.popups.settings.js to settingsDialog.js
* Blank tests for now. Needs Qunit integration tests.
* Transform into a factory function for future testing.
* Saving functionality is commented out, will be removed when immplemented in
the actions
* Add new incomplete action saveSettings
* Will perform the saveSettings async tasks and then trigger enabling or
disabling popups.
* Rename action settingsDialogClosed to hideSettings for consistency
Change-Id: I3936d3a4bc476de16d76025139be09f1798796c4
The changeListener is not wired up, so nothing will actually happen if you
click the link or cog. You should see redux actions flow trying to show it
though.
Change-Id: I29e629db63a4511a76c132f44f2ebf13254a4c6f
Since the user can dwell on a link, abandon it while moving to dwell on
the preview and vice versa:
* The time at which the link/preview was abandoned is recorded and can
be updated.
* The event can only be queued when the link/preview has definitely been
abandoned.
Reducer changes:
* Make the eventLogging reducer:
* Calculate the time it took to show the preview.
* Mark the interaction as finished when the user abandons the link or
the preview.
* Queue a "dismissed" event if the preview hasn't been shown or a
"dwelledButAbandoned" event if it has when the abandon has
finalized.
Bug: T152225
Change-Id: I6a254136f615484fc26e440fe5125289e74688a6
Reducer changes:
* Make the eventLogging reducer queue an "opened" event with the
requisite supporting data.
Changes:
* Update the Popups EventLogging schema to the latest revision, which
defines the "opened" action.
Bug: T152225
Change-Id: I9d67daf83815f1c08b6479497c566dfa337de4bc
Action changes:
* Mix in timing information into actions that are likely to need it:
LINK_DWELL, {LINK,PREVIEW}_ABANDON_START, LINK_CLICK, and
PREVIEW_CLICK.
* Generate and include an unique token in the LINK_CLICK action.
Reducer changes:
* Make the eventLogging reducer:
* Handle the LINK_CLICK action's new shape.
* Start (create) and maintain a model of the user interacting with a
link.
Bug: T152225
Change-Id: I671b12432ba2f7a93bf81043adb57ac30a4c38c3
Move all of the change listeners into
resources/ext.popups/changeListeners and remove the ChangeListener
suffix. Also, do the above for the associated tests.
Bug: T152225
Change-Id: I90ada465ea291d601f8f1c5c6e775148a2100319
Action changes:
* Add the PREVIEW_SHOW action.
Reducer changes:
* Increment the user's preview count in the eventLogging reducer.
Changes:
* Dispatch the PREVIEW_SHOW action when the preview has been shown.
* Add the previewCount change listener, which is responsible for
persisting the user's preview count to storage when it changes.
* Call the change listener factories individually in
#registerChangeListeners as their signatures aren't consistent.
Bug: T152225
Change-Id: Ifb493c5bff66712a25614ebb905251e43375420a
Action changes:
* Include the user's preview count in the user property of the action.
Reducer changes:
* Make the eventLogging reducer add the bucketed user's preview count to
the state tree.
Changes:
* Extract mw.popups.UserSettings#getPreviewCount and #setPreviewCount
and associated tests from the ext.popups.core module.
Bug: T152225
Change-Id: I6b7afef31311be8fede685deb536f577845cb9cf
Action changes:
* Group user-related data in the user property, rather than repeating
"isUser" and "user" prefixes.
* Include user's edit count in the user property of the action.
Reducer changes:
* Make the preview reducer handle the action's new shape.
* Make the eventLogging reducer add the bucketed user's edit count to
the state tree.
Bug: T152225
Change-Id: I8fae9e2d0f6889ffdd30bb5192513d194f791967
Action changes:
* Include whether the user is logged in/out and information about the
current page in the BOOT action.
* Add the EVENT_LOGGED action, which represents the eventLoggined change
listener logging the queued event.
Reducer changes:
* Move all tokens and timing information from the preview reducer to the
eventLogging reducer.
* Make the eventLogging reducer reset the state.
Changes:
* Add the mw.popups.createSchema function, which constructs an instance
of the mw.eventLog.Schema object that can be used to log Popups
events.
* Add the eventLogging change listener, which logs the queued event.
* Add hand-crafted, artisanal documentation.
Bug: T152225
Change-Id: I8a3f58358b211cc55417dcda7e796fe538e3d910
This reverts commit 047bccfac1.
It created merge conflicts with a bunch of patches that were days old and about to be merged. Instead of rebasing 10 patches, let's revert this one, finish merging the other ones and just rebase and fix this one. I'll re-introduce the patch in a bit.
Change-Id: Ib495755b0ab4bfa5fdf5590b1271792862a47d4b
Since the state was cloned into an empty object with $.extend, undefined
properties were being deleted from it, not actually preserving those
keys. So:
nextState({hi: undefined, ho: 1}, {ho: 2})
//> {ho: 2}
It seems like a more consistent behavior would be to not lose any own
keys on the state as we do with the updates too, so that:
nextState({hi: undefined, ho: 1}, {ho: 2})
//> {hi: undefined, ho: 2}
Which is what this commit does by not using $.extend to clone the state
and instead just manually copy the keys to the new object, even the
undefined ones.
Change-Id: If4f2a3b0d25bb5ef34cfbc1f2c9c0b5479aeee9b
Changes:
* Make the gateway handle missing pages, which are characterised by the
MediaWiki API response having both the missing property set to truthy
and the page not having any revisions.
* Add the preview-empty template and associated "mwe-popups-is-empty"
CSS class, which describe what an empty preview contains and how it
should look.
Supporting changes:
* Move the original preview template into the ext.popups module.
Bug: T151054
Change-Id: Ife75bf9c6bafdfe0a6cc3e20eea853b4ac8f951b
The preview reducer would treat the LINK_ABANDON_END and
PREVIEW_ABANDON_END actions as the PREVIEW_DWELL action. Fortunately,
this was a NOOP as they would only fall through if the preview was being
dwelled upon.
HT Joaquin Hernandez.
Change-Id: I01ff47de34ac41f1e6aa46aa5baccc2a27013f1b
Per T150814#2833030.
Changes:
* Round the preview's border.
* Adjust the shadow cast by the preview.
* Make both fade-in and -out animations last 200 ms.
Bug: T150814
Change-Id: I55c728680ebb208e7cd1bd4c99a8453ae9915f2e
It would seem that nextState should be $.extend({}, state, updates), but
as it was noted in the commit message that introduced the function
$.extend doesn't copy undefined|null values and that's why we iterate
manually over updates to copy any prop that exists over. That way we can
override properties to null|undefined in the state.
This commit expands the comment to explain so, and why OO.copy couldn't
be used.
Change-Id: If6c7119a4713328bb23c8f77042500510d515049
Instead of defaulting the config to the global mw.config when the param
is not defined, always pass it in (it is called just once in application
code), that way there's no need to test for the optional argument
behavior and the function is pure.
Change-Id: Ib1addb3060826f58dce2d6f928252ce1888a4293
Given this UI elements are going to change this comment would get
outdated really soon. Instead refer to generic interaction.
Change-Id: Icf56a864c47847bdef23985e9afd702ccb0de3b7
I59ac2e32 removed support for non-SVG capable UAs but didn't remove all
of the associated styles.
Additional changes:
* Give the inner container a name, "mwe-popups-container", so that it
can be styled with reduced specificity.
Supporting changes:
* Move the "core" styles into the ext.popups module.
Bug: T151054
Change-Id: I8deb6e76daf6f33fcb6f496129e6baf9e6793231
I14b437e7 introduced a regression where neither the preview's thumbnail
nor extract linked to the page.
Change-Id: I51793640d882aec711af8683ffbea794fad1b047
Action creator changes:
* Make the linkAbandon action creator asynchronous by splitting it into
two distinct actions, LINK_ABANDON_START and _END, the latter of which
is dispatched after a 300 ms delay.
* Introduce the previewDwell and previewAbandon action creators. The
latter is an asynchronous action that mirrors the linkAbandon action.
Reducer changes:
* Make the LINK_DWELL, LINK_ABANDON_END, and PREVIEW_ABANDON_END action
hide a preview, if one has been shown.
* Make the LINK_ABANDON_END action NOOP if:
* The user has interacted with another link, or
* The user is interacting with the preview.
Supporting changes:
* Update the mw.popups.reducers#preview and #renderer unit tests to use
an empty previous state so that the tests are more resilient to
modifications of the state tree.
Change-Id: I2ecf575bbb59bb64772f75da9b5a29c071b46a8d
I14b437e7 introduced a regression where the `moment`ed last modified
timestamp wasn't rendered.
Additional changes:
* Remove the HTML comments from the preview template.
Change-Id: I78047dd0f8acc6292e0592887e128e6046119212
If the user abandons the link after the API request delay (500 ms) but
before the it resolves (~10e3 ms), then the preview shouldn't be
rendered.
Changes:
* actions: Include the link in the FETCH_START, FETCH_FAILED, and
FETCH_END actions.
* reducers: If the active link has changed, then FETCH_END is a NOOP.
Supporting changes:
* reducers: Signal that a preview should be rendered and shown with
preview.shouldShow.
Change-Id: I3dd1c0c566ec63de515174c14845d7927583ce93
The QUnit test suite now completes in ~10e2 ms rather than ~10e3 ms.
Changes:
* Make mw.popups.actions#linkDwell to use mw.popups.wait.
* Make the tests for mw.popups.actions#linkDwell complete faster, but
still asynchronously, by stubbing mw.popups.wait.
Change-Id: I5cbef0ea69bc860f75cac27c1adea3d419c1ffad
Changes:
* Reduce the fade-in animation delay to 200 ms.
* Truncate a long extract by fading it out gradually.
* Increase the depth of the shadow cast by a preview and remove its
border.
Bug: T150814
Change-Id: I2ec0c0472bc24767bbf1f4db000cc9d690454629
Extract core rendering functionality from the mw.popups.renderer and
mw.popups.renderer.article objects.
For now, render and show the preview when the user dwells on and
abandons a link respectively.
Supporting changes:
* Add mw.popups.wait, which is sugar around window.setTimeout.
* action.response -> action.result in the FETCH_END case of the preview
reducer.
Change-Id: I14b437e7c2f55b988837fcb2800dd61a23c29a01
Supporting changes:
* Remove the preview.previousActiveLink property from the state tree as
it's unnecessary.
Change-Id: I657decf9425a7a9e2b27a798ed60b162569661d8
OO.copy doesn't copy Element instances, whereas $.extend does. However,
OO.copy does copy properties whose values are undefined or null, whereas
$.extend doesn't.
Since the state tree contains an Element instance - the
preview.activeLink property - we need to use $.extend.
Add the nextState helper function which copies the current state tree
with $.extend and mixes in all updates manually.
Change-Id: Ie8edd9fa0cc3a62a792ed60b49288f85b3ca73e9
If the user has abandoned the link or dwelled on a different link, then
don't make the API request.
Changes:
* Fix a bug in the linkDwell reducer where the activeLink was always
being set to undefined.
* Add the private fetch action creator.
* Make the linkDwell action dispatch the result of the fetch action
creator after 500ms.
Supporting changes:
* Make the link* action creators take DOM elements rather than jQuery
instances so that:
1. Testing whether the state tree has changed is an identity
comparison.
2. jQuery instances are constructed only when required.
* Document the ext.popups.Gateway type.
* Document the Redux.Store type.
* Rename the "previews-page-title" data attribute to
"page-previews-title" to avoid confusion.
Change-Id: I0b1cf3337a6f8d6450ad2bd127cb292ebb73af4f
Supporting changes:
* Add mw.popups.registerChangeListener, which registers a change
listener that will only be called when the state in the store has
changed.
Change-Id: Ibe6934058327c7f02f7d8092e74a667a5a1c600a
Changes:
* Add sessionToken and pageToken properties to the BOOT action and
update the preview reducer.
Supporting changes:
* Move the mw.popups.createActions to ext.popups/boot.js so that Redux
is used in one file and the actions can be tested in isolation more
easily.
Change-Id: Icd61bf1aeb466899e047432bf9798e2574652830
Reducers as a whole are a WIP, but this implements a baseline from which
to add more.
Changes:
* Create ext.popups.reducers to house all reducers
* Create reducers for preview and renderer state manipulation
* Create rootReducer by combining preview and renderer reducers
* Add QUnit tests for reducers
* Move action types into ext.popups.actionTypes
* Extract rootReducer from boot.js
Change-Id: I8a2296c6846cd4b0552a485e671af1d974944195
Supporting changes:
* Automatically register JavaScript files in the
tests/qunit/ext.popups/ directory.
Additional changes:
* Fix a grammatical error in the docblock for
mw.popups.createExperiment.
Change-Id: Ieb00709e353f0b960375fdaa0ca0dcdf950f2eb9
Changes:
* Make grunt:qunit run all QUnit tests in those modules whose names
being with "ext.popups".
* Add ext.popups/index.js, which initialises the mw.popups namespace.
* Add ext.popups/userSettings.js, which contains the code that deals
with interacting with the User Agent's storage.
* Add ext.popups/experiment.js, which contains the code that that
decides whether or not the user is in the experiment condition.
* Add tests for both units, converting existing tests where appropriate.
* Remove the associated code from ext.popups.core/ext.popups.core.js.
* Finally, dispatch the BOOT action against the store in
ext.popups/boot.js.
Change-Id: I697207677304bd49c7cfe1d37bb0a4af7810f387
Also, fix a bug introduced in Ib7168217 wherein the non-existent
Redux.thunk was referenced rather than ReduxThunk.default.
Change-Id: Ia4cc28b16b17442de69ed84bb8e8c88a6a9f201d
Changes:
* Create the ext.popups.lib module, which contains redux@3.6.0 and
redux-thunk@2.1.0.
* Rely on the Resource Loader's minification and mangling (?)
mechanisms.
* Create an asynchronous bootstrap script, which creates a Redux store
when the User Agent is idle.
Change-Id: Ib7168217a5673bb2a8378eb30d6aa45043c66e62
There is one reference to removeTooltips in
ext.popups.targets.desktopTarget.
I suspect this got broken in a rebase. It seems Jenkins only runs
browser tests post merge. We should fix that.
Please resubmit the patch with this amended.
This reverts commit 0ff40a6532.
Change-Id: Idd8dffb853db760ebc5866190d008f173e3025ba
Tooltips are intended to be stripped upon `mouseenter` and `focus`
events and then restored during their corresponding `mouseleave` and
`blur` events. This was broken due to duplication of event registration
and no proper deregistration.
Changes:
* Rename `mw.popups.removeTooltips` to `mw.popups.removeTooltip` to
more accurately describe its effect
* Narrow the scope of `mw.popups.removeTooltip`
* Add `mw.popups.restoreTooltip`
* Add `onLinkBlur` to `desktopTarget.js` to handle tooltip restoration
* Update qunit test to reflect changes to functions
* Minor hygiene changes regarding event namespaces
Bug: T142723
Change-Id: I776a72e436ac823fdd6b68435d9a042a91c934e5
If a user has hovercards disabled, when they right click a link
this will trigger another hover event which will reset dwellStartTime.
This means when a dwelledButAbandoned event fires shortly afterwards
the totalInteractionTime will not be correct.
To remedy this, the calculation of totalInteractionTime and
perceivedWait is moved into ext.popups.schemaPopups
Now that we can trigger events without logging to the server and
checking the total interaction time duration in two places,
let's always run the event and only check it once.
A `hover` event triggers the setting of a dwell start time
A `display` event triggers the setting of the perceivedWait value
* Both are reset on a dwelledButAbandoned.
Since dwellStartTime is controlled inside a single place, getMassageData
no longer needs to clear it.
The test "returns false if dwelledButAbandoned event without a dwellStartTime"
is removed as this should no longer be possible.
Bug: T147846
Change-Id: Ie5917ca86f0d0ab27f4cf507e6dfa2c271433c03
This adds two new events "display" and "hover" which are not
recorded back to the server. The benefits of having these events
is that they are important events in the lifecycle of a hovercard.
This allows us to debug trackSubscribe and ensure we see the behaviour
we expect to see and in a future patchset will allow us to use these
events to drive the calculation of interaction time in one single location
(Sneak preview:
https://gerrit.wikimedia.org/r/316481 to get a feel for the why.)
Change-Id: I58eefc29444179fd245cfd722093dedea19455e8
I plan to track events that will not be logged by the schema so
am dropping the 'schema' from the topic name.
This will allow us to track events that we do not log via the schema
Change-Id: I0c2762f7ed6e54fff765513b2c2d32f73fe8902f
Since DWELL_EVENTS_MIN_INTERACTION_TIME is always
zero the check will always be true so let's not make
that check unnecessarily.
We might change this in future is not a good reason
for keeping this code.
Change-Id: I23cb7ef9caeb3df470ccf109b815c4c566b0a735
Given we currently have modules defined in extension.json and in hooks
it can be really confusing understanding how the code fits together.
This change hopefully makes this a little clearer by using folder names
that are named after the resource loader modules - this is also consistent
with how we do things in our other extensions.
A images folder is added to the route so that it is clearer that the images
are not used in ResourceLoader module definitions and are only used to illustrate
the beta feature.
Change-Id: Ia650ec03e3a6d3069165441ddfa069d390be4d10
* Make it clearer what event is being bound, consistent with
onLinkClick and onLinkAbandon
* Don't create event data twice
* Refactor to reduce function size
Change-Id: Ie4368531612a2829ad191629410ba548eadb2007
Per T143051, hovercards was asked to be closed after the user clicks on
the hovercard (or the link that showed it). Closing the popup before
logging the `click` event causes `logData` to be lost. This patch logs
the data first and then clears it.
The regression was introduced in Ifd6f75c2a53d8d7b5ef9fd3f232f85b55eea24c8.
Also do not attempt closing a popup when it may not be open.
Bug: T146934
Change-Id: I02febc83036130bcea0a769114c9126cb481bafe
Per T143051, hovercards was asked to be closed after the user clicks on
the hovercard (or the link that showed it). Doing so before logging the
`dismiss` event caused `logData` to be lost. This patch logs the data first
and the clears it.
The regression was introduced in I3f3c4780cc31dc8d84cdd76df2c77fa45fbea882
Bug: T146927
Change-Id: Ie965d43b04962b2dbe2d15caa4c14bf62d1e39ea
The dismiss event is currently a side effect of closing a popup.
This should be more closely coupled with the event that causes it.
This allows the closePopup method to be called without trigging
an event which is a necessary precursor to closing popups when
navigating away from the page.
Change-Id: I3f3c4780cc31dc8d84cdd76df2c77fa45fbea882
The parameter types are incorrect and this leads to confusion
Use $ prefix for $link parameter to make clear it is a jQuery.Object
Change-Id: I3f98f3729cd06aedd791e7503233082c1402dc95
The handler for the hook `wikipage.content` was long
and undocumented but is a crucial piece of code.
To make it a little easier for people not so familiar with the code
to find this code and understand what it does I've pulled it out into
a named function.
Change-Id: I3ada53e135dea7dc6846440999b0d42285e14013
ext.popups.experiment depends on .core as it initialized the mw.popups
namespace and .core depends on .experiments for
mw.popups#getEnabledState.
By merging the experiment module into core, we can eliminate any
circular dependencies.
Changes:
* Move ext.popups.experiment.js code into ext.popups.core.js
* Remove mw.popups.experiment module and any references to it
Note: ext.popups.experiment.test.js was left in its own file for cleaner
QUnit module setups and easier removal later. I'm not entirely happy
with doing it this way, but I'm not sure changing the mw.config within
the mw.popups.core QUnit module is worth merging the files.
Bug: T146035
Change-Id: I1f024567010acaa61c1d613c6e59c998198a5976
Extract the minimum interaction time of dwelledButAbandoned events to
a unique place: mw.popups.render.DWELL_EVENTS_MIN_INTERACTION_TIME
Lower that interaction time to 0 so that all dwelledButAbandoned events
are logged.
Bug: T145379
Change-Id: Id68183367966b9f0d52e0cd570cab64671a3e87e
When hovercards are off clicking of a link will log the click
event as many times as you hovered over the link prior to clicking.
To prevent this, stop listening to old events before listening to
new ones.
Bug: T143805
Change-Id: I3e0dd2d1f259cdadfd3e02c67a137697540ca955
Improving Hovercards' settings dialog to fulfill design specification.
Also fixing HTML structure by removing invalid `radiogroup` element and
adding missing `</div>` element, fixing related QUnit test.
Changes:
* Add close icon instead of using text
* Style header as a table for alignment
* Remove redundant "OK" button and have it replace "Save" instead
* Update text of "OK" button to "Done"
* Fix description for translation of "Done" button
* Fix qunit and selenium tests
* Remove unnecessary markup and less
* Add mediawiki-ui-button and mediawiki-ui-icon dependencies
* Shrink dialog width some per design spec
* Fix dialog horizontal position calculation to remove hard-coded value
Bug: T138612
Change-Id: I7395e3438836149becdd576942bdaf6f21b4163f
The schema introduces a new field called `hovercardsSuppressedByGadget`,
which is `true` when the Navigation Popups gadget, rather than the Popups
extensions, is being used to fetch and display article summary.
Note that it may take some time before the Navigation Popups gadget is
loaded onto the page, thus actions taking place before this happens will
record the value of `hovercardsSuppressedByGadget` as `false`. This is
mostly the case with the `pageLoaded` action which almost always happens
before the gadget code is loaded.
Bug: T137203
Change-Id: Ie31deea7ae2323d6a346c67ed84fdf587ad55bd1
* Change labels in English for settings options
* Update description for enable option
* Remove description for disable option
Bug: T138233
Change-Id: Id23dcc7b7e655f7939bb2e455b8680ed5a2c6331
These errors do not have any value, they just happen when the user
cancels the current request. Removing these events will result in
less noise for data analysis.
Bug: T137059
Change-Id: Ia9d921553791d1b7be5941a98716297b74b706b2
Tested in IE9 and Safari. It seems in Safari the mixture of jQuery
and setAttributeNS causes issues.
Bug: T138430
Change-Id: I4bc63da18d008487d0c8f7b906688e4c8c809efd
Aligning Hovercards' Less to Coding Standards and also variablize
`linkpreview-title` font-family.
Change-Id: I11f2d71ce50dcd0fe47f3c5c528779e29a81cbc6
Before this change we only used to check whether NavPopups gadget is
enabled once per page load. The premise was that we could figure out
whether the gadget was enabled easily given the module name. Since
the gadget module name can be different on diffirent wikis, that
solution would not scale.
With this change we check whether the gadget is enabled before each
hover over an eligible link. We rely on the existence of the global
`window.pg` object. The existence of the object means that the
gadget is enabled, thus we do not show Hovercards.
Bug: T135628
Change-Id: Ica154dd3bfd913202a8b558ea4b10ad177176f83
This is temporary fix to get Hovercards not to show up when
Navigation Popups gadget is enabled on huwiki. The gadget module is
named 'ext.gadget.latszer' and not 'ext.gadget.Navigation_popups'.
Also check whether the global 'pg' variable is created, which means
the Navigation Popups gadget is enabled.
Bug: T135630
Change-Id: I35e1b911967200bfdfd8f44ad4e4b8dcfd844ee7
Unlike what was previously implemented, this patch does not care whether
the user hovers over another link while dismissing the popup.
The `dismissed` action is correctly logged in these cases too.
Bug: T136649
Change-Id: I68473cb8b66bae53213bce186345ca1ce436573f
According to caniuse.com SVG support is available
from IE > 8, Firefox > 3, Safari > 3.1 and Android
> 2.3. Android 3-4.3 does not support masking.
Out of all these browsers, considering market share
and ResourceLoader support, none of these browsers
are of concern to us. In IE8 for example we do not
run JavaScript for our end users. Thus we should remove
this fallback support.
Changes
* Remove createImgThumbnail method and its test
* Groups duplicate CSS groups
* Refactor createThumbnail function
** Leave a FIXME on some curious code
Change-Id: I59ac2e320b2e07815bc4136d5942016fdc1d4340
Bug: T135554
article.surveyLink, article.SIZES and currentRequest do not need to be
globally available on mw.popups.render object. They can be local variables.
Similarly openTimer and closeTimer should not be public APIs.
Changes:
* Add an abort method for purpose of aborting existing requests.
Change-Id: Ic2add9c611990bf80e8b80ab154563f6551a77ea
Use the standardised MediaWiki storage system for the simple use
case of disabling/enabling Popups. The jStorage library is 12kb
uncompressed and cannot be justified for this usage (and if it becomes
the standardised library mw.storage will begin using it)
This means that browsers with full localStorage or no localStorage
support will not be able to disable Popups. Given the current ecosystem
of the web - localStorage is widely supported - and the fact that grade
A browsers enjoy localStorage support - this is not a problem.
See https://github.com/wikimedia/mediawiki/blob/REL1_27/resources/src/startup.js#L59
Changes:
* Stop using jStorage
* Cleanup and migrate previous values in jStorage with plan for removing this
in a month.
Bug: T136241
Change-Id: I6dac2911e84d6cb20731be34add01576cf407c46
To avoid sentence parsing bugs in other languages.
We have to artificially remove the always-added ellipsis from textextracts to
mimic previous behavior, and we'll add ellipsis via CSS afterwards.
Bug: T135824
Change-Id: Idf27f2fd18f7197e588c609eeb62ac8fc80626d7
This action was sent correctly when popups are enabled, but not when
disabled. This commit sends this event also when popups are disabled
so that we are able to compare the metric with popups enabled vs disabled.
Additional changes:
* Chain events in resources/ext.popups.targets/desktopTarget.js
* Add a separate property to the list of defaults and fix formatting.
Bug: T131315
Change-Id: I426f0a1a735b8fe6b16f3d2695d9099dd0d0469b
* Remove floats;
* Get rid of margin collapsing so that the space is easy to understand;
* Fix invalid rules.
Bug: T135629
Change-Id: I3bfaf137e4d02f0dc809c809edac9b28cb4bdc3a
Changes:
* Disable the desktop target by default
* If the user is in the experiment condition, then enable the desktop
target
* Add PopupsExperiment config var, which, if set to true, causes: the
experiment config to be added to the output as config vars, as well as
the ext.popups.desktop Resource Loader module
Bug: T132604
Change-Id: Ia71ca924c3e2ec2ee0b0191ea2573fa7ff5e8a7e
As there are an unmanageable amount of synchronous checks of
mw.popups.enabled, convert mw.popups.experiment.isUserInCondition to a
synchronous method.
Follow on I4959749.
Bug: T132604
Change-Id: Ide07e62868c77bfcd78af58dcec7303a35a72157
Breaks EventLogging as the old schema is not compatible with these
new properties. We will reapply the patch later when in a better state.
My bad for merging.
This reverts commit ca20031a0e.
Change-Id: Ia961e0f99339f9045af9d0a4653599a48518cc95
Changes:
* Add the ext.popups.experiment module
* Add the mw.popups.experiment.isUserInCondition function, which
returns a promise that resolves with true if the user is in the
experimental condition, otherwise false
* If the experiment isn't configured, i.e. wgPopupsExperimentConfig is
null or undefined, then the user isn't entered into the experiment,
providing a kill switch
Bug: T132604
Change-Id: I49597494273e3862711a32e4951c8598e6c8bf59
IE9 does support SVG if you use setAttributeNS.
Thus stop whitelisting SVG support there.
Don't worry about fallback rendering of SVG for IE < 9
- those that do not support SVG also do not
enjoy ResourceLoader JavaScript support.
Bug: T134979
Change-Id: I1d3d9c4c622e98df19a5e9dc4101b44242e07178
This change is an intermediate step in our transition
to logging a variety of events easily.
Also:
* Some events may need sendBeacon support and may not be
logged if the navigator does not support sendBeacon.
* Do not load schema code if EventLogging is not available.
Bug: T131315
Change-Id: Iff939577f65f1c6c71701dd6967939445385fb70
* The classes in ext.popups.core.less apply to the thumbnail
which reside in .mwe-popups > div > a.popups-discreet
The thumbnail is thus not a direct child of the div parent of
popups-discreet.
* The margin-top is unnecessary.
Change-Id: If91140a55baa1aef36483002de681503c2690cf6
Popups currently makes use of a render cache. Using a cache in this
way without protection causes problems (I will look at cleaning this up)
The hack below it
`mw.popups.$popup.html( mw.popups.$popup.html() );`
will lead to the html of the cached object being wiped out on IE9 meaning
future loads will show an empty popup.
Add a unit test (which previously would fail in IE9) to protect against this
in future.
Bug: T68496
Change-Id: Icef784fb389b0ab1856e2ba7464c9423ebcd62ab
Changes:
* Extract survey link element creation into
mw.popups.render.renderers.article#createSurveyLink
* Make #createSurveyLink throw an error if the URL doesn't start with
https or http
* Add unit tests that cover the new behaviour of #createSurveyLink
Bug: T129177
Change-Id: I8b61cb0e94ab4e30bc894c279bb05918ecc7719e
Changes:
* Quote the URL with double quotes when generating the background-image
rule
Bug: T129177
Change-Id: I74748c7efe67954272ce0a539455b0b00001a26a
1. Add comment for empty SPAN when there is no thumbnail
2. Use footer instead of div.timestamp-* as it also contains
the settings icon now.
Change-Id: Ia6fca32770596c980b33a9a6e58bb08b661b90d1
Test pieces that make sense, everything else is already
covered in cucumber tests. See the following commit for more
info: I55f311b6b8845e6ebf4cc5698758afd1f9042a45.
Bug: T133025
Change-Id: I474c1569494601ae5865dcfba22ea728220ff8df
API requests to fetch the hovercards data now include
`X-Analytics: preview=1` header so that HoverCard hovers are
easily distinguishable in Hive.
Bug: T129425
Change-Id: I69df51a627951c4373b3b7463ab5b2c0a129faa1
Linkpreview will try to fetch a text extract using the api and, if this
doesn't fail, show the extract as a drawer with a button "Continue to
article". If the query fails, it will redirect the user to the article
directly.
Bug: T113243
Depends-On: I6d8c5b80e70c3d8d1a92a70cc91e1b90d598cb0f
Change-Id: Idbaae9fe2decd89b73e623a25fbd39464c316fb2
Zopfli is the most efficient DEFLATE compression algorithm, trading run-time
performance for file sizes that are typically 3-8% smaller than those produced
by zlib with the maximum compression setting. Its output is Deflate-compatible,
so no specialized decoder is needed.
This change was created by running zopflipng against all the PNG files in this
repository. The exact invocation was:
git ls-files --exclude-per-directory=.gitignore -- '*.png' \|
parallel zopflipng -m -y {} {} \;
Files which zopflipng was not able to compress more efficiently were left unmodified.
Bug: T127608
Change-Id: I3ec96a8e75ea521315b5944e91ead5e60297c6df
Zopfli is the most efficient DEFLATE compression algorithm, trading run-time
performance for file sizes that are typically 3-8% smaller than those produced
by zlib with the maximum compression setting. Its output is Deflate-compatible,
so no specialized decoder is needed.
This change was created by running zopflipng against all the PNG files in this
repository. The exact invocation was:
git ls-files --exclude-per-directory=.gitignore -- '*.png' \|
parallel zopflipng -m -y {} {} \;
Files which zopflipng was not able to compress more efficiently were left unmodified.
Bug: T127608
Change-Id: I0bcc35a4d27a7589cd1a3f6569ef8089e8b6ec02
For the work on T113243, the Popups extension should be structured in a
more flexible way. This is achieved with this change.
Following has changed:
* The main/core logic of Popups now lives in ext.popups.core to be shareable
between implementations
* The desktop specific logic lives in ext.popups.desktop now, the frontend init
code in ext.popups.desktopTarget and the desktop renderer in
ext.popups.renderer.desktopRenderer
This change doesn't change the functionality of Popups.
Change-Id: I72121e0a1e4b2952f85dc1bc8cf59d06b8d22f47
This doesn't need to be a property. Its being used exactly once, and
because we try to test for NavigationPopup's availability so soon we
mostly get an incorrect answer.
Moving the condition to the render method instead. Chances of NavPop
being loaded when the settings' screen is being rendered are much
higher.
Bug: T109912
Change-Id: I3723dc1e3e9400b6ed2e0160104c849a25a71881
mw.RegExp.escape() is already used in ext.popups.core.js and
the dependency to module 'mediawiki.RegExp' is set.
Change-Id: Iaa7ab6902693c787234fd589276fa38ce75b82da
Right now the main renderer always picks the article renderer, no matter
if any other renderers is registered. It will now run the 'matcher'
method in the rendered, and if it returns true, we use that renderer.
Not sure how we'll avoid matchers stepping on each other.
Bug: T69434
Bug: T102921
Change-Id: Ib06812836cdbd3a5bfd54d4bc6147012fb891694
Adds the jscs and jshint packages for development and their tasks in
Grunt. Also fixes all the code convention errors.
Change-Id: If1c9dfdbe22d4912d78b6a51b1292866970a85cc
The global disablePopups function from NavigationPopups got scoped to
pg.fn.disabledPopups at some point. We were relying on that function
to both detect and disable the gadget.
Bug: T109912
Change-Id: I3d6de60ca2a387e45675ddb04cdc45b0f967e46a
Don't request unused prop=info and its rvprop=watched;
use formatversion=2 instead of indexpageids to simplify processing the
returned query object.
Bug: T103981
Change-Id: I1c0f9b0245a823413f5fed78bc1d0d46ef978cef
Popups' API query request specifies the string 'true' as the value for
some boolean request parameters, but that's functionally identical to
specifying boolean true -- both get encoded as param=true in the HTTP
request.
Change-Id: Icc5f4b8ef6faaffe4a23c964f8cd8c2582d28381
Replace $.escapeRE from 'jquery.mwExtension' by
mw.RegExp.escape from 'mediawiki.RegExp'.
Bug: T103610
Change-Id: I1d23e4c02d92828291b98a52b4e8050fbebc06d9
mw.Uri throws an exception when dealing with -
href="javascript:void(0);"
href="mailto:abc@example.com"
etc.
Using a try…catch to return undefined in this case.
Bug: T95215
Change-Id: I632e9dc0e70a5fddf9f2573572bfc8e7f6232923
This is needed for wikis that use LanguageConverter, since the title
attribute is converted to the user's variant, and the canonical title is
needed for the API unless converttitles is specified.
For filtering, instead of comparing linkHref and expectedHref, filter
out links that have other query parameters or aren't in content
namespaces.
Bug: T93605
Change-Id: I5534753307ed5e1d4b27c52c616fd143b2a397e1
Based on the comments this is what it supposed to be.
mw.popups.render.article does the API-queries on init, so do that after
the API_DELAY-timer fired.
Change-Id: Ia235cbe1eb86fc774edda84208d320843401624e
Both the title and the extract were being html escaped thus producing
string like ' and " when used with .text(). So, we now use
document.createTextNode() for the normal text and .text() with the bolded
one.
Bug: T93720
Change-Id: I6bbc52e427dc636b7b0be1ad4f749d9273ff61b3
If the URL of the thumbnail has suspicious characters like ', " or \
return a <span> instead of trying to render a thumbnail.
Bug: T88171
Change-Id: Ide052ea2a7de166599d077a385a6e788bfa63302
Instead of replacing all instances of the title in the extract -
'$1<b>$2</b>$3'
We now put symbolic strings there which we use to split the string
and then make an array of text and <b> elements that get appended
to $contentbox.
Bug: T76378
Change-Id: I02222bbff84532f63cac67af1bf889c328ec6ff2
Use proven technology to create and compare URLs.
This will display popups also on anchored links again.
Change-Id: Ic010ca027017435f666782e709e641cf3bbb8767
Hotfix for Ie34064860a81c7866b8e8b86858d2e12a8a196f4
Still won't show up popups for anchored links, but dunno if intended.
Change-Id: I91a15153cb8bcae6d8ef2e5616855e4d45be6d78
Use the getUrl method to check that the <a> actually links
to the article that it has the title of. Only those elements
are returned by selectPopupElements.
Bug: T70039
Bug: T72512
Change-Id: Ie34064860a81c7866b8e8b86858d2e12a8a196f4
This is a subset of patch Ie340648. If reviewing and merging the much
larger other patch (it does much more things) is a problem, we can
merge this first, rebase the other one and have a much more focussed
discussion.
Change-Id: I4549fb1810c7dd36df8a70983d9508015c2bfadf
HTML5 allows <a> elements with no href="..." attribute. We do this in
Wikibase/Wikidata in a few places. Hovering these <a> elements causes
TypeErrors.
This is a hotfix. Please see Ie340648 for a much more advanced fix.
Change-Id: Ib20ef8348c964a6ba736d0fc76909fd4d496c11e
- Don't prevent the link click event.
- Check with the currentLink element rather than jQuery selectoin.
- Add click handler to images (used to be only extract).
- Stop the 'closePopup' if 'reset' has already been run.
Bug: T86378
Change-Id: I8748ecffe55954425656c5103fa9ddc99b6f3f72
This <div> had been sitting visible at the bottom of the page
and went unnoticed till it caused problems with the ContentTranslation
extension.
Hiding it using 'display: none;' causes issues with the masking
of the images, thus putting the div out of the view port.
Bug: T76718
Change-Id: I731128c827aa093e0ffab52dc378aea386b0bb3c
Currently .mwe-popups-extract keeps some empty space after the last
line. This shifts a little when zooming in causing part of the text
of the next line to be visible. Reducing this to have lesser extra
empty space solves the problem.
Bug: 73551
Change-Id: I968fca23fe2de04cb3f73ba4e7d4f676fbf88536
When zooming in the border of the div is visible over the :after
pseudo element.
- Update top and bottom triangle mixins to include @extra argument
- Update pseudo elements to use the new mixin and position them
correctly according the extra size
Bug: 73550
Change-Id: I05b9c74a675c69e407c4c78771504f447da754c5
Hovercards is currently at 5 z-index which causes
it to be rendered behind the compact personal bar.
Changing this also effects the border triangles and
masked SVGs, thus incrementing them too.
Bug: 72882
Change-Id: Ib3c889c748a9c919754d8281e68fd0664db7c408
This was happening due to:
* Stale CSS selector
* Incorrect margin values
Also added missing triangle pokey for a particular
orientation of the hovercard.
Bug: 71872
Change-Id: Ic4986f9cee2a92b29548ef21f9bec3f2c2117e98
This code has not been working because processAllPopups does
not execute. Test the change with:
https://en.wikipedia.org/wiki/User:Prtksxna/common.js
Bug: 62952
Change-Id: I3c8b5590b89693743c85c006fc0ee0a50e8b8342
The script depends on a title being present in title attribute. So
skip links without title attributes (which were getting empty
attributes due to the implementation of removeTooltips) and bail on
trying to open a preview for links without a title.
Bug: 67728
Change-Id: I4cc744bea10af34741681f11e03d77b3d53e3a3b
removeBracketsFromText doesn't count it tracks nesting level, and
brackets are [] not (). Minor detail.
Change-Id: I8f42b1ccae5233d7b6062bb311eced6ef3085d4a
Per discussion on the bug, the current values of 150ms/100ms cause a
lot of unintended actions.
Bug: 64234
Change-Id: I6fe2d89ad97630ec5c7f47d3e3b9b71d7cfc5d3f
In combination with other gadgets the error
TypeError: re.query is undefined
can occur because the request contains titles:'' and the response is [].
Change-Id: I46d02e7c48a55cd9af20fd7ef729b4d26f69a8c0
Casees:
1) Hello (and welcome)
2) Hello )and welcome(
3) (Hello (and) welcome)
The current RegExp only takes care of (1). The new code should
take care of all the cases.
Bug: 65138
Change-Id: I39f38beed0cf612067d6fc61b18295d1d38fcc22
These links were not ignored due to a typo. This also threw an error,
because these links produced query.interwiki and not in query.pages.
Change-Id: I3b5c5b900209323e3e72b41e3b02e90f1f53b4eb
Instead of the current incomprehensible mixture of em's and px's.
This will help resolve other positioning bugs with relative ease.
Change-Id: I9d7659736489c461ab8c0f4aa660a3ce2846bd5d
The setting is called 'underline' and defaults to 'Skin or
browser default' (= 2). If set to 'Always' (= 1), which is what
I personally like and do, ;-) all text in hovercards is
underlined (and the underlines disappear if you hover the
hovercard, which is a bit tricky but possible).
This simple fix removes the dependency from the default style
(which only shows underlines on hover). I think this is the most
straightforward solution.
Change-Id: Ide54ffd1949a50184d8d2a680bf1a0d35e24d563