Merge "Rename BlockRestriction -> BlockRestrictionStore and wire it up as a service"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / dm / ChangesListViewModel.js
1 /**
2 * View model for the changes list
3 *
4 * @class mw.rcfilters.dm.ChangesListViewModel
5 * @mixins OO.EventEmitter
6 *
7 * @param {jQuery} $initialFieldset The initial server-generated legacy form content
8 * @constructor
9 */
10 var ChangesListViewModel = function MwRcfiltersDmChangesListViewModel( $initialFieldset ) {
11 // Mixin constructor
12 OO.EventEmitter.call( this );
13
14 this.valid = true;
15 this.newChangesExist = false;
16 this.liveUpdate = false;
17 this.unseenWatchedChanges = false;
18
19 this.extractNextFrom( $initialFieldset );
20 };
21
22 /* Initialization */
23 OO.initClass( ChangesListViewModel );
24 OO.mixinClass( ChangesListViewModel, OO.EventEmitter );
25
26 /* Events */
27
28 /**
29 * @event invalidate
30 *
31 * The list of changes is now invalid (out of date)
32 */
33
34 /**
35 * @event update
36 * @param {jQuery|string} $changesListContent List of changes
37 * @param {jQuery} $fieldset Server-generated form
38 * @param {string} noResultsDetails Type of no result error
39 * @param {boolean} isInitialDOM Whether the previous dom variables are from the initial page load
40 * @param {boolean} fromLiveUpdate These are new changes fetched via Live Update
41 *
42 * The list of changes has been updated
43 */
44
45 /**
46 * @event newChangesExist
47 * @param {boolean} newChangesExist
48 *
49 * The existence of changes newer than those currently displayed has changed.
50 */
51
52 /**
53 * @event liveUpdateChange
54 * @param {boolean} enable
55 *
56 * The state of the 'live update' feature has changed.
57 */
58
59 /* Methods */
60
61 /**
62 * Invalidate the list of changes
63 *
64 * @fires invalidate
65 */
66 ChangesListViewModel.prototype.invalidate = function () {
67 if ( this.valid ) {
68 this.valid = false;
69 this.emit( 'invalidate' );
70 }
71 };
72
73 /**
74 * Update the model with an updated list of changes
75 *
76 * @param {jQuery|string} changesListContent
77 * @param {jQuery} $fieldset
78 * @param {string} noResultsDetails Type of no result error
79 * @param {boolean} [isInitialDOM] Using the initial (already attached) DOM elements
80 * @param {boolean} [separateOldAndNew] Whether a logical separation between old and new changes is needed
81 * @fires update
82 */
83 ChangesListViewModel.prototype.update = function ( changesListContent, $fieldset, noResultsDetails, isInitialDOM, separateOldAndNew ) {
84 var from = this.nextFrom;
85 this.valid = true;
86 this.extractNextFrom( $fieldset );
87 this.checkForUnseenWatchedChanges( changesListContent );
88 this.emit( 'update', changesListContent, $fieldset, noResultsDetails, isInitialDOM, separateOldAndNew ? from : null );
89 };
90
91 /**
92 * Specify whether new changes exist
93 *
94 * @param {boolean} newChangesExist
95 * @fires newChangesExist
96 */
97 ChangesListViewModel.prototype.setNewChangesExist = function ( newChangesExist ) {
98 if ( newChangesExist !== this.newChangesExist ) {
99 this.newChangesExist = newChangesExist;
100 this.emit( 'newChangesExist', newChangesExist );
101 }
102 };
103
104 /**
105 * @return {boolean} Whether new changes exist
106 */
107 ChangesListViewModel.prototype.getNewChangesExist = function () {
108 return this.newChangesExist;
109 };
110
111 /**
112 * Extract the value of the 'from' parameter from a link in the field set
113 *
114 * @param {jQuery} $fieldset
115 */
116 ChangesListViewModel.prototype.extractNextFrom = function ( $fieldset ) {
117 var data = $fieldset.find( '.rclistfrom > a, .wlinfo' ).data( 'params' );
118 if ( data && data.from ) {
119 this.nextFrom = data.from;
120 this.nextFromFormatted = data.fromFormatted;
121 }
122 };
123
124 /**
125 * @return {string} The 'from' parameter that can be used to query new changes
126 */
127 ChangesListViewModel.prototype.getNextFrom = function () {
128 return this.nextFrom;
129 };
130
131 /**
132 * @return {string} The 'from' parameter formatted per the user's datetime format preference
133 */
134 ChangesListViewModel.prototype.getNextFromFormatted = function () {
135 return this.nextFromFormatted;
136 };
137
138 /**
139 * Toggle the 'live update' feature on/off
140 *
141 * @param {boolean} enable
142 */
143 ChangesListViewModel.prototype.toggleLiveUpdate = function ( enable ) {
144 enable = enable === undefined ? !this.liveUpdate : enable;
145 if ( enable !== this.liveUpdate ) {
146 this.liveUpdate = enable;
147 this.emit( 'liveUpdateChange', this.liveUpdate );
148 }
149 };
150
151 /**
152 * @return {boolean} The 'live update' feature is enabled
153 */
154 ChangesListViewModel.prototype.getLiveUpdate = function () {
155 return this.liveUpdate;
156 };
157
158 /**
159 * Check if some of the given changes watched and unseen
160 *
161 * @param {jQuery|string} changeslistContent
162 */
163 ChangesListViewModel.prototype.checkForUnseenWatchedChanges = function ( changeslistContent ) {
164 this.unseenWatchedChanges = changeslistContent !== 'NO_RESULTS' &&
165 changeslistContent.find( '.mw-changeslist-line-watched' ).length > 0;
166 };
167
168 /**
169 * @return {boolean} Whether some of the current changes are watched and unseen
170 */
171 ChangesListViewModel.prototype.hasUnseenWatchedChanges = function () {
172 return this.unseenWatchedChanges;
173 };
174
175 module.exports = ChangesListViewModel;