NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name whatcd gazelle toggle bookmarks // @include /https?://www\.empornium\.(me|sx)/torrents\.php.*/ // @include /https?://www\.empornium\.(me|sx)/user\.php.*/ // @include /https?://www\.empornium\.(me|sx)/top10\.php.*/ // @include /https?://femdomcult\.org/torrents\.php.*/ // @include /https?://femdomcult\.org/user\.php.*/ // @include /https?://femdomcult\.org/top10\.php.*/ // @version 3 // @require http://code.jquery.com/jquery-2.1.1.js // @grant GM_addStyle // @grant GM_unsafeWindow // ==/UserScript== "use strict"; // Changelog: // * version 3 // - fixed missing non-breaking space on empty title // * version 2 // - improved hover over download icon // * version 1 // - initial version GM_addStyle('' + '.toggle-bookmarks {' + ' position: absolute;' + ' display: none;' + ' padding-right: 5px;' + ' z-index: 2;' + '}' + '.toggle-bookmarks .wrapper {' + ' background: white;' + ' border-radius: 3px;' + ' border: 1px solid silver;' + '}' + '.toggle-bookmarks.bookmarked .add,' + '.toggle-bookmarks:not(.bookmarked) .remove {' + ' display: none;' + '}' + '.toggle-bookmarks svg {' + ' width: 15px;' + ' height: 15px;' + '}' + ''); var star_add = [ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 179.99999" height=', '"180" width="180"><path d="M37.048 171.56l52.9-38.433 52.9 38.434-20.204-62', '.187 52.9-38.435h-65.388L89.95 8.748 69.74 70.938H4.352l52.9 38.435z" fill-', 'rule="evenodd" stroke="#000"/><g transform="matrix(1.278 0 0 1.278 -195.438', '-298.745)"><circle r="30" cy="337.362" cx="260" fill="#fff" stroke="#000" s', 'troke-width="3.13"/><rect ry="5" y="317.283" x="255" height="40.159" width=', '"10" rx="5"/><rect ry="5" y="332.362" x="239.92" height="10" width="40.159"', 'rx="5"/></g></svg>' ].join(''); var star_remove = [ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 179.99999" height=', '"180" width="180"><path d="M37.048 171.56l52.9-38.433 52.9 38.434-20.204-62', '.187 52.9-38.435h-65.388L89.95 8.748 69.74 70.938H4.352l52.9 38.435z" fill-', 'rule="evenodd" stroke="#000"/><g transform="matrix(1.278 0 0 1.278 -195.438', '-298.745)"><circle r="30" cy="337.362" cx="260" fill="#fff" stroke="#000" s', 'troke-width="3.13"/><rect ry="5" y="332.362" x="239.92" height="10" width="', '40.159" rx="5"/></g></svg>' ].join(''); this.jQuery = jQuery.noConflict(true); function Ajax() { this.add = jQuery.proxy(this.add, this); this.remove = jQuery.proxy(this.remove, this); } Ajax.prototype.get = function (action, torrent_id) { return jQuery.get('bookmarks.php', { action: action, type: 'torrent', auth: unsafeWindow.authkey, id: torrent_id }); }; Ajax.prototype.add = function (torrent_id) { return this.get('add', torrent_id); }; Ajax.prototype.remove = function (torrent_id) { return this.get('remove', torrent_id); }; function ToggleBookmark() { this.el = this.create_el(); this.id = null; this.ids = {}; this.ajax = new Ajax(); this.symbol_bookmark = '★'; this.on_mouseenter_title = jQuery.proxy(this.on_mouseenter_title, this); this.on_mouseenter_version = jQuery.proxy(this.on_mouseenter_version, this); this.on_mouseleave = jQuery.proxy(this.on_mouseleave, this); this.add = jQuery.proxy(this.add, this); this.remove = jQuery.proxy(this.remove, this); this.el.appendTo('body'); this.attach_events(); } ToggleBookmark.prototype.remove_char = function (value, index) { return value.slice(0, index) + value.slice(index + 1); }; ToggleBookmark.prototype.remove_bookmark_symbol = function (title) { var bookmark_index = title.lastIndexOf(this.symbol_bookmark); if (bookmark_index === -1) return title; return this.remove_char(title, bookmark_index); }; ToggleBookmark.prototype.create_el = function () { return jQuery([ '<div class="toggle-bookmarks">', ' <div class="wrapper">', ' <a href="#" class="add">', star_add, '</a>', ' <a href="#" class="remove">', star_remove, '</a>', ' </div>', '</div>', ].join('')); }; ToggleBookmark.prototype.attach_events = function () { var title_selector = [ 'td.cats_col + td > a[href^="torrents.php?id"]', 'td.cats_cols + td > a[href^="torrents.php?id"]' ].join(','); var version_selector = [ 'td.cats_col + td .version', 'td.cats_cols + td .version' ].join(','); var torrent_table = jQuery('.torrent_table'); torrent_table.on('mouseenter', title_selector, this.on_mouseenter_title); torrent_table.on('mouseenter', version_selector, this.on_mouseenter_version); torrent_table.on('mouseleave', 'td', this.on_mouseleave); this.el.on('click', 'a.add', this.add); this.el.on('click', 'a.remove', this.remove); }; ToggleBookmark.prototype.add = function (event) { event.preventDefault(); var callback = jQuery.proxy(this.added, { self: this, title: this.title, id: this.id }); this.ajax.add(this.id).done(callback); }; ToggleBookmark.prototype.remove = function (event) { event.preventDefault(); var callback = jQuery.proxy(this.removed, { self: this, title: this.title, id: this.id }); this.ajax.remove(this.id).done(callback); }; ToggleBookmark.prototype.on_toggle = function (id, value) { this.ids[id] = value; this.el.toggleClass('bookmarked', value); }; ToggleBookmark.prototype.added = function () { var title = this.self.remove_bookmark_symbol(this.title.textContent).trim(); if (title) this.title.textContent = title + '\u00a0' + this.self.symbol_bookmark; else this.title.textContent = this.self.symbol_bookmark; this.self.on_toggle(this.id, true); }; ToggleBookmark.prototype.removed = function () { var title = this.self.remove_bookmark_symbol(this.title.textContent).trim(); if (title) this.title.textContent = title; else this.title.textContent = '\u00a0'; this.self.on_toggle(this.id, false); }; ToggleBookmark.prototype.is_version_bookmarked = function (title) { return title.text().indexOf('★') !== -1; }; ToggleBookmark.prototype.is_title_bookmarked = function (parent) { return parent.find('> span > img[alt="bookmarked"]').length > 0; }; ToggleBookmark.prototype.get_id = function (title) { return title.attr('href').match(/id=(\d+)/)[1]; }; ToggleBookmark.prototype.rect = function (el) { var offset = el.offset(); var width = el.width(); var height = el.height(); var center = { top: offset.top + height / 2, left: offset.left + width / 2 }; return { left: offset.left, right: offset.left + width, top: offset.top, bottom: offset.top + height, center: center, width: width, height: height }; }; ToggleBookmark.prototype.on_mouseenter = function (title, parent, is_bookmarked) { var id = this.get_id(title); var bookmarked = this.ids[id]; if (bookmarked === undefined) { bookmarked = is_bookmarked.call(this); } this.id = id; this.title = title.contents() .filter(function () {return this.nodeType === 3}) .filter(function () {return this.textContent.length > 0}) .first()[0]; this.el.toggleClass('bookmarked', bookmarked); this.el.prependTo(title); this.el.show(); } ToggleBookmark.prototype.on_mouseenter_title = function (event) { var title = jQuery(event.currentTarget); var parent = title.parent(); var is_bookmarked = function() {return this.is_title_bookmarked(parent)}; this.on_mouseenter(title, parent, is_bookmarked); var rect_title = this.rect(title); this.set_offset({ top: rect_title.center.top, left: rect_title.left }); }; ToggleBookmark.prototype.on_mouseenter_version = function (event) { var title = jQuery(event.currentTarget).find('.collapsed-title'); var parent = title.parent(); var is_bookmarked = function () {return this.is_version_bookmarked(title);} this.on_mouseenter(title, parent, is_bookmarked); var rect_title = this.rect(title); var rect_parent = this.rect(parent); this.set_offset({ top: rect_title.center.top, left: rect_parent.left }); }; ToggleBookmark.prototype.on_mouseleave = function (event) { this.el.hide(); }; ToggleBookmark.prototype.set_offset = function (offset) { this.el.offset({ top: offset.top - this.el.innerHeight() / 2, left: offset.left - this.el.innerWidth() }); }; new ToggleBookmark();