filtersPage.js
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25  */
26 
27 
28 var Cc = Components.classes;
29 var Ci = Components.interfaces;
30 var Cu = Components.utils;
31 var Cr = Components.results;
32 
33 Cu.import("resource://app/jsmodules/sbProperties.jsm");
34 Cu.import("resource://app/jsmodules/sbLibraryUtils.jsm");
35 Cu.import("resource://app/jsmodules/kPlaylistCommands.jsm");
36 Cu.import("resource://app/jsmodules/SBDataRemoteUtils.jsm");
37 
50 window.mediaPage = {
51 
52  // The sbIMediaListView that this page is to display
53  _mediaListView: null,
54 
55  // The sb-playlist XBL binding
56  _playlist: null,
57 
58  // Collection of splitters
59  _splitters: [],
60 
64  get mediaListView() {
65  return this._mediaListView;
66  },
67 
68 
74  set mediaListView(value) {
75 
76  if (!this._mediaListView) {
77  this._mediaListView = value;
78  } else {
79  throw new Error("mediaListView may only be set once. Please reload the page");
80  }
81  },
82 
83 
87  get isOnlyView() false,
88 
89 
95  onLoad: function(e) {
96  if (!this._mediaListView) {
97  Components.utils.reportError("playlistPage.xul did not receive " +
98  "a mediaListView before the onload event!");
99  return;
100  }
101 
102  var servicePaneNode =
103  Cc["@songbirdnest.com/servicepane/library;1"]
104  .getService(Ci.sbILibraryServicePaneService)
105  .getNodeFromMediaListView(this._mediaListView);
106  if (servicePaneNode) {
107  document.title = servicePaneNode.displayName;
108  }
109  else {
110  // failed to find the node, stick with the media list name
111  document.title = this._mediaListView.mediaList.name;
112  }
113 
114  this._playlist = document.getElementById("playlist");
115 
116  // Configure the playlist filters based on the querystring
117  this._updateFilterLists();
118  this._generateFilters();
119 
120  // Get playlist commands (context menu, keyboard shortcuts, toolbar)
121  // Note: playlist commands currently depend on the playlist widget.
122  var mgr =
123  Components.classes["@songbirdnest.com/Songbird/PlaylistCommandsManager;1"]
124  .createInstance(Components.interfaces.sbIPlaylistCommandsManager);
125  var cmds = mgr.request(kPlaylistCommands.MEDIAITEM_DEFAULT);
126 
127  // Set up the playlist widget
128  this._playlist.bind(this._mediaListView, cmds);
129 
130  // Adjust the height of the filter pane to be proportional to the height
131  // of the display pane. Only do this if the |sb-playlist-splitter| sizing
132  // prefs do not exist. (i.e. first run).
133  var prefs = Application.prefs;
134  if (!prefs.has("songbird.splitter.sb-playlist-splitter.before.height") &&
135  !prefs.has("songbird.splitter.sb-playlist-splitter.after.height"))
136  {
137  var splitter = document.getElementById("sb-playlist-splitter");
138  if (splitter) {
139  var page = document.getElementById("sb-playlist-media-page");
140  var pageHeight = page.boxObject.height;
141 
142  // Make the filter pane cover 30% of the area
143  const FILTER_COVER_AREA = 0.30;
144  var splitFactor = parseInt(pageHeight * FILTER_COVER_AREA);
145 
146  // Make sure the splitter covers lines completely
147  var filterTree = document.getElementById("sb-filterlist-tree");
148  var rowLineHeight = parseInt(getComputedStyle(filterTree, "").lineHeight);
149  if (splitFactor % rowLineHeight != 0) {
150  splitFactor = rowLineHeight * (Math.round(splitFactor / rowLineHeight));
151  }
152 
153  // Finally, adjust the splitter spacing
154  splitter.setBeforeHeight(splitFactor);
155  splitter.setAfterHeight(pageHeight - splitFactor);
156  }
157  }
158  },
159 
160 
164  onUnload: function(e) {
165  for (var s = 0; s < this._splitters.length; s++) {
166  this._splitters[s].removeEventListener("mousemove", this._onFilterSplitterMove, true);
167  this._splitters[s].removeEventListener("mousedown", this._onFilterSplitterDown, true);
168  this._splitters[s].removeEventListener("mouseup", this._onFilterSplitterUp, true);
169  }
170 
171  if (this._playlist) {
172  this._playlist.destroy();
173  this._playlist = null;
174  }
175  },
176 
177 
182  highlightItem: function(aIndex) {
183  this._playlist.highlightItem(aIndex);
184  },
185 
189  canDrop: function(aEvent, aSession) {
190  return this._playlist._canDrop(aEvent);
191  },
192 
196  onDrop: function(aEvent, aSession) {
197  return this._playlist.
198  _dropOnTree(-1,
199  Ci.sbIMediaListViewTreeViewObserver.DROP_AFTER,
200  aSession);
201  },
202 
207  _parseQueryString: function() {
208  var queryString = (location.search || "?").substr(1).split("&");
209  var queryObject = {};
210  var key, value;
211  for each (var pair in queryString) {
212  [key, value] = pair.split("=");
213  queryObject[key] = unescape(value);
214  }
215  return queryObject;
216  },
217 
221  _updateFilterLists: function() {
222 
223  // This URL is registered as two different media pages.
224  // One with filters, one without.
225  // Use the querystring to determine what to show.
226  var queryString = this._parseQueryString();
227 
228  var filters = this._mediaListView.cascadeFilterSet;
229 
230  // Set up standard filters if not already present.
231  // Note that the first filter should be search.
232  if (filters.length <= 1) {
233  // Restore the last library filterset or set our default
234  var filterSet = SBDataGetStringValue( "library.filterset" );
235  if ( filterSet.length > 0 ) {
236  filterSet = filterSet.split(";");
237  }
238  else {
239  filterSet = [];
240  }
241 
242  // if we have fewer than the default number of filters, append some extra
243  var defaultFilterSet = [
244  SBProperties.genre,
245  SBProperties.artistName,
246  SBProperties.albumName
247  ];
248  for (var i = filterSet.length; i < defaultFilterSet.length; i++) {
249  filterSet.push(defaultFilterSet[i]);
250  }
251 
252  for each (var filter in filterSet) {
253  filters.appendFilter(filter);
254  }
255  }
256  },
257 
261  _generateFilters: function() {
262  // Hide the playlist splitter
263  var psplitter = document.getElementById("sb-playlist-splitter");
264  psplitter.setAttribute("hidden","true");
265 
266  // Get and empty the parent
267  var parent = document.getElementById("sb-playlist-filters");
268  while (parent.firstChild) {
269  parent.removeChild(parent.firstChild);
270  };
271 
272  // Create the filters based upon the cascadeFilterSet data.
273  var cfs = this.mediaListView.cascadeFilterSet;
274  var length = cfs.length;
275  var filters = [];
276 
277  for (var i = 0; i < length; i++) {
278  // If this is a search then keep going.
279  if (cfs.isSearch(i)) {
280  continue;
281  }
282 
283  // And start creating the filter
284  var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
285  var filterlist = document.createElementNS(XUL_NS, "sb-filterlist");
286  filterlist.setAttribute("enableColumnDrag", "false");
287  filterlist.setAttribute("flex", "1");
288 
289  if (this.mediaListView instanceof Ci.sbIFilterableMediaListView) {
290  let constraint = this.mediaListView.filterConstraint;
291  if (constraint) {
292  for (let group in ArrayConverter.JSEnum(constraint.groups)) {
293  if (!(group instanceof Ci.sbILibraryConstraintGroup )) {
294  continue;
295  }
296  if (!group.hasProperty(SBProperties.contentType)) {
297  continue;
298  }
299  let types =
300  ArrayConverter.JSArray(group.getValues(SBProperties.contentType));
301  if (types.length == 1) {
302  filterlist.setAttribute("filter-category-value", types[0]);
303  break;
304  }
305  }
306  }
307  }
308 
309  parent.appendChild(filterlist);
310 
311  filterlist.bind(this.mediaListView, i);
312  filters.push(filterlist);
313 
314  if (i < length - 1) {
315  var splitter = document.createElement("sb-smart-splitter");
316  splitter.setAttribute("id", "filter_splitter" );
317  splitter.setAttribute("stateid", "filter_splitter_" + cfs.getProperty(i) + this.mediaListView.mediaList.guid );
318  splitter.setAttribute("state", "open");
319  splitter.setAttribute("resizebefore", "closest");
320  splitter.setAttribute("resizeafter", "closest");
321  splitter.setAttribute("collapse", "never");
322 
323  var grippy = document.createElement( "grippy" );
324  splitter.appendChild(grippy);
325  // do not appendChild now, wait until all filterlists have been created (see below)
326  this._splitters.push(splitter);
327  }
328  }
329 
330  // once the filterlists have been created, insert the splitters are their appropriate spot.
331  // we do this now rather than during the filter creation loop because the splitters
332  // need to be able to find their before/after targets on construction (so as to be able
333  // to reload their positions correctly), so if we did do appendChild in the previous loop,
334  // the after target would never be found, and the positions would be wrong
335  for (var s=0;s<this._splitters.length;s++) {
336  var splitter = this._splitters[s];
337  parent.insertBefore(splitter, filters[s+1]);
338  }
339 
340  // If we didn't actually add any filters then hide the filter box.
341  if (!parent.firstChild) {
342  parent.setAttribute("hidden", "true");
343  } else {
344  // Once we know we have at least one filter, show the playlist splitter.
345  psplitter.removeAttribute("hidden");
346  }
347  }
348 } // End window.mediaPage
349 
350 
var Ci
Definition: filtersPage.js:29
var Cr
Definition: filtersPage.js:31
var Application
Definition: sbAboutDRM.js:37
const XUL_NS
Definition: FeedWriter.js:83
var Cc
Definition: filtersPage.js:28
const char * types
function SBDataGetStringValue(aKey)
Get the value of the data in string format.
let window
Lastfm onLoad
Definition: mini.js:36
return null
Definition: FeedWriter.js:1143
var prefs
Definition: FeedWriter.js:1169
countRef value
Definition: FeedWriter.js:1423
var Cu
Definition: filtersPage.js:30
function onUnload()
onUnload - called when the cover preview window unloads.
Definition: coverPreview.js:36
_getSelectedPageStyle s i
Array filter(tab.attributes, function(aAttr){return(_this.xulAttributes.indexOf(aAttr.name) >-1);}).forEach(tab.removeAttribute
var group