mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
967 lines
42 KiB
JavaScript
967 lines
42 KiB
JavaScript
NEWSBLUR.ReaderClassifierTrainer = function(options) {
|
|
var defaults = {
|
|
'width': 620,
|
|
'training': true,
|
|
modal_container_class: "NB-full-container NB-classifier-container"
|
|
};
|
|
|
|
this.flags = {
|
|
'publisher': true,
|
|
'story': false,
|
|
'modal_loading': false,
|
|
'modal_loaded': false
|
|
};
|
|
this.cache = {};
|
|
this.trainer_iterator = -1;
|
|
this.feed_id = null;
|
|
this.options = $.extend({}, defaults, options);
|
|
this.model = NEWSBLUR.assets;
|
|
this.runner_trainer();
|
|
};
|
|
|
|
NEWSBLUR.ReaderClassifierFeed = function(feed_id, options) {
|
|
var defaults = {
|
|
'width': 620,
|
|
'training': false,
|
|
'feed_loaded': true,
|
|
modal_container_class: "NB-full-container NB-classifier-container"
|
|
};
|
|
|
|
this.flags = {
|
|
'publisher': true,
|
|
'story': false,
|
|
'modal_loading': false,
|
|
'modal_loaded': false
|
|
};
|
|
this.cache = {};
|
|
this.feed_id = feed_id;
|
|
this.trainer_iterator = -1;
|
|
this.options = $.extend({}, defaults, options);
|
|
this.model = NEWSBLUR.assets;
|
|
this.runner_feed();
|
|
};
|
|
|
|
|
|
NEWSBLUR.ReaderClassifierStory = function(story_id, feed_id, options) {
|
|
var defaults = {
|
|
'width': 620,
|
|
'feed_loaded': true,
|
|
modal_container_class: "NB-full-container NB-classifier-container"
|
|
};
|
|
|
|
this.flags = {
|
|
'publisher': false,
|
|
'story': true,
|
|
'modal_loading': false,
|
|
'modal_loaded': false
|
|
};
|
|
this.cache = {};
|
|
this.story_id = story_id;
|
|
this.feed_id = feed_id;
|
|
this.original_feed_id = feed_id;
|
|
// if (options.social_feed_id) this.feed_id = options.social_feed_id;
|
|
this.trainer_iterator = -1;
|
|
this.options = $.extend({}, defaults, options);
|
|
this.model = NEWSBLUR.assets;
|
|
this.runner_story();
|
|
};
|
|
|
|
var classifier_prototype = {
|
|
|
|
runner_trainer: function(reload) {
|
|
if (!reload) {
|
|
this.user_classifiers = {};
|
|
}
|
|
|
|
this.make_trainer_intro();
|
|
this.get_feeds_trainer();
|
|
this.handle_cancel();
|
|
this.open_modal();
|
|
|
|
this.model.preference('has_trained_intelligence', true);
|
|
NEWSBLUR.reader.check_hide_getting_started();
|
|
|
|
this.$modal.parent().bind('click.reader_classifer', $.rescope(this.handle_clicks, this));
|
|
},
|
|
|
|
runner_feed: function() {
|
|
this.options.social_feed = _.string.include(this.feed_id, 'social:');
|
|
|
|
if (!this.model.classifiers[this.feed_id]) {
|
|
this.model.classifiers[this.feed_id] = _.extend({}, this.model.defaults['classifiers']);
|
|
}
|
|
|
|
if (this.options.feed_loaded) {
|
|
this.user_classifiers = this.model.classifiers[this.feed_id];
|
|
} else {
|
|
this.user_classifiers = {};
|
|
}
|
|
this.find_story_and_feed();
|
|
this.make_modal_feed();
|
|
this.make_modal_title();
|
|
this.handle_cancel();
|
|
this.open_modal(_.bind(function() {
|
|
this.fit_classifiers();
|
|
}, this));
|
|
this.$modal.parent().bind('click.reader_classifer', $.rescope(this.handle_clicks, this));
|
|
|
|
if (!this.options.feed_loaded) {
|
|
_.defer(_.bind(function() {
|
|
this.load_single_feed_trainer();
|
|
}, this));
|
|
}
|
|
},
|
|
|
|
runner_story: function() {
|
|
this.options.social_feed = _.string.include(this.feed_id, 'social:');
|
|
|
|
if (!this.model.classifiers[this.feed_id]) {
|
|
this.model.classifiers[this.feed_id] = _.extend({}, this.model.defaults['classifiers']);
|
|
}
|
|
|
|
if (this.options.feed_loaded) {
|
|
this.user_classifiers = this.model.classifiers[this.feed_id];
|
|
} else {
|
|
this.user_classifiers = {};
|
|
}
|
|
|
|
this.find_story_and_feed();
|
|
this.make_modal_story();
|
|
this.handle_text_highlight();
|
|
this.make_modal_title();
|
|
this.handle_cancel();
|
|
this.open_modal(_.bind(function() {
|
|
this.fit_classifiers();
|
|
}, this));
|
|
this.$modal.parent().bind('click.reader_classifer', $.rescope(this.handle_clicks, this));
|
|
|
|
if (!this.options.feed_loaded) {
|
|
_.defer(_.bind(function() {
|
|
this.load_single_feed_trainer();
|
|
}, this));
|
|
}
|
|
},
|
|
|
|
load_previous_feed_in_trainer: function() {
|
|
var trainer_data_length = this.trainer_data.length;
|
|
this.trainer_iterator = this.trainer_iterator - 1;
|
|
var trainer_data = this.trainer_data[this.trainer_iterator];
|
|
// NEWSBLUR.log(['load_previous_feed_in_trainer', this.trainer_iterator, trainer_data]);
|
|
if (!trainer_data || this.trainer_iterator < 0) {
|
|
this.make_trainer_intro();
|
|
this.reload_modal();
|
|
} else {
|
|
this.feed_id = trainer_data['feed_id'];
|
|
this.load_feed(trainer_data);
|
|
}
|
|
},
|
|
|
|
load_next_feed_in_trainer: function() {
|
|
var trainer_data_length = this.trainer_data.length;
|
|
this.trainer_iterator += 1;
|
|
var trainer_data = this.trainer_data[this.trainer_iterator];
|
|
// NEWSBLUR.log(['load_next_feed_in_trainer', this.trainer_iterator, trainer_data]);
|
|
if (!trainer_data || this.trainer_iterator >= trainer_data_length) {
|
|
this.make_trainer_outro();
|
|
this.reload_modal();
|
|
this.load_feeds_trainer(null, this.trainer_data);
|
|
} else {
|
|
this.feed_id = trainer_data['feed_id'];
|
|
if (this.model.get_feed(this.feed_id)) {
|
|
this.load_feed(trainer_data);
|
|
} else {
|
|
this.load_next_feed_in_trainer();
|
|
}
|
|
}
|
|
},
|
|
|
|
load_feed: function(trainer_data) {
|
|
this.feed_id = trainer_data['feed_id'] || trainer_data['id'];
|
|
this.feed = this.model.get_feed(this.feed_id);
|
|
this.feed_tags = trainer_data['feed_tags'];
|
|
this.feed_authors = trainer_data['feed_authors'];
|
|
this.user_classifiers = trainer_data['classifiers'];
|
|
this.feed_publishers = new Backbone.Collection(trainer_data['popular_publishers']);
|
|
this.feed.set('num_subscribers', trainer_data['num_subscribers'], {silent: true});
|
|
this.options.feed_loaded = true;
|
|
|
|
if (!this.model.classifiers[this.feed_id]) {
|
|
this.model.classifiers[this.feed_id] = _.extend({}, this.model.defaults['classifiers']);
|
|
}
|
|
|
|
if (this.feed_id in this.cache) {
|
|
this.$modal = this.cache[this.feed_id];
|
|
} else {
|
|
if (this.flags['story']) {
|
|
this.make_modal_story();
|
|
this.handle_text_highlight();
|
|
} else if (this.flags['publisher']) {
|
|
this.make_modal_feed();
|
|
this.make_modal_trainer_count();
|
|
}
|
|
this.make_modal_title();
|
|
}
|
|
|
|
this.reload_modal();
|
|
},
|
|
|
|
reload_modal: function(callback) {
|
|
this.flags.modal_loading = setInterval(_.bind(function() {
|
|
if (this.flags.modal_loaded) {
|
|
clearInterval(this.flags.modal_loading);
|
|
$('.NB-modal').empty().append(this.$modal.children());
|
|
this.$modal = $('.NB-modal'); // This is bonkers. I shouldn't have to reattach like this
|
|
$(window).trigger('resize.simplemodal');
|
|
this.handle_cancel();
|
|
this.$modal.parent().scrollTop(0);
|
|
callback && callback();
|
|
this.fit_classifiers();
|
|
}
|
|
}, this), 125);
|
|
},
|
|
|
|
fit_classifiers: function() {
|
|
var $form = $("form", this.$modal);
|
|
if (!$form.length) return;
|
|
var form_height = $form.innerHeight();
|
|
var form_outerheight = $form.outerHeight(true);
|
|
var offset_top = $form.position().top;
|
|
var offset_bottom = $(".NB-modal-submit-bottom", this.$modal).outerHeight(true);
|
|
var container_height = $(".simplemodal-container").height();
|
|
var new_form_height;
|
|
var i = 0;
|
|
while (form_outerheight + offset_top + offset_bottom > container_height) {
|
|
// console.log(["fit_classifiers", form_outerheight, offset_top, offset_bottom, container_height]);
|
|
i++;
|
|
$form.height(form_height - 1);
|
|
new_form_height = $form.innerHeight();
|
|
form_outerheight = $form.outerHeight(true);
|
|
if (new_form_height == form_height || i > 500) break;
|
|
form_height = Math.min(new_form_height, form_height-1);
|
|
}
|
|
},
|
|
|
|
get_feeds_trainer: function() {
|
|
this.model.get_feeds_trainer(null, $.rescope(this.load_feeds_trainer, this));
|
|
},
|
|
|
|
load_feeds_trainer: function(e, data) {
|
|
var $begin = $('.NB-modal-submit-begin', this.$modal);
|
|
|
|
this.trainer_data = data;
|
|
|
|
if (!data || !data.length) {
|
|
this.make_trainer_outro();
|
|
this.reload_modal();
|
|
} else {
|
|
$begin.text('Begin Training')
|
|
.addClass('NB-modal-submit-green')
|
|
.removeClass('NB-modal-submit-grey')
|
|
.removeClass('NB-disabled');
|
|
}
|
|
},
|
|
|
|
retrain_all_sites: function() {
|
|
$('.NB-modal-submit-reset', this.$modal).text('Rewinding...').attr('disabled', true).addClass('NB-disabled');
|
|
|
|
this.model.retrain_all_sites(_.bind(function(data) {
|
|
this.load_feeds_trainer(null, data);
|
|
this.load_next_feed_in_trainer();
|
|
}, this));
|
|
},
|
|
|
|
find_story_and_feed: function() {
|
|
if (this.story_id) {
|
|
this.story = this.model.get_story(this.story_id);
|
|
}
|
|
|
|
this.feed = this.model.get_feed(this.feed_id);
|
|
|
|
if (this.options.feed_loaded && this.feed) {
|
|
this.feed_tags = this.model.get_feed_tags();
|
|
this.feed_authors = this.model.get_feed_authors();
|
|
$('.NB-modal-subtitle .NB-modal-feed-image', this.$modal).attr('src', $.favicon(this.feed));
|
|
$('.NB-modal-subtitle .NB-modal-feed-title', this.$modal).html(this.feed.get('feed_title'));
|
|
$('.NB-modal-subtitle .NB-modal-feed-subscribers', this.$modal).html(Inflector.pluralize(' subscriber', this.feed.get('num_subscribers'), true));
|
|
}
|
|
},
|
|
|
|
load_single_feed_trainer: function() {
|
|
var self = this;
|
|
var $loading = $('.NB-modal-loading', this.$modal);
|
|
$loading.addClass('NB-active');
|
|
|
|
var get_trainer_fn = this.model.get_feeds_trainer;
|
|
if (this.options.social_feed) {
|
|
get_trainer_fn = this.model.get_social_trainer;
|
|
}
|
|
get_trainer_fn.call(this.model, this.feed_id, function(data) {
|
|
self.trainer_data = data;
|
|
if (data && data.length) {
|
|
// Should only be one feed
|
|
self.load_feed(data[0]);
|
|
}
|
|
});
|
|
},
|
|
|
|
make_trainer_intro: function() {
|
|
var self = this;
|
|
|
|
this.$modal = $.make('div', { className: 'NB-modal-classifiers NB-modal NB-modal-trainer'}, [
|
|
$.make('h2', { className: 'NB-modal-title' }, [
|
|
$.make('div', { className: 'NB-icon' }),
|
|
'Intelligence Trainer',
|
|
$.make('div', { className: 'NB-icon-dropdown' })
|
|
]),
|
|
$.make('h3', { className: 'NB-modal-subtitle' }, 'Here\'s what to do:'),
|
|
$.make('ol', { className: 'NB-trainer-points NB-classifiers' }, [
|
|
$.make('li', [
|
|
$.make('div', { className: 'NB-classifier-example' }),
|
|
$.make('b', 'You will see a bunch of tags and authors.'),
|
|
' Sites will be ordered by popularity. Click on what you like and don\'t like.'
|
|
]),
|
|
$.make('li', [
|
|
$.make('b', 'The intelligence slider filters stories.'),
|
|
$.make('img', { className: 'NB-trainer-bullet', src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/indicator-focus.svg'}),
|
|
' are stories you like',
|
|
$.make('br'),
|
|
$.make('img', { className: 'NB-trainer-bullet', src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/indicator-unread.svg'}),
|
|
' are stories you have not yet rated',
|
|
$.make('br'),
|
|
$.make('img', { className: 'NB-trainer-bullet', src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/indicator-hidden.svg'}),
|
|
' are stories you don\'t like'
|
|
]),
|
|
$.make('li', [
|
|
// $.make('img', { src: NEWSBLUR.Globals.MEDIA_URL + '/img/reader/sample_menu.png', style: 'float: right', width: 176, height: 118 }),
|
|
$.make('b', 'Stop any time you like.'),
|
|
' You can easily train individual stories as you read.'
|
|
])
|
|
]),
|
|
(!NEWSBLUR.Globals.is_authenticated && $.make('div', { className: 'NB-trainer-not-authenticated' }, 'Please create an account and add sites you read. Then you can train them.')),
|
|
$.make('div', { className: 'NB-modal-submit-bottom' }, [
|
|
$.make('div', { className: 'NB-modal-submit' }, [
|
|
(!NEWSBLUR.Globals.is_authenticated && $.make('div', { className: 'NB-modal-submit-grey NB-modal-submit-button' }, 'Close')),
|
|
(NEWSBLUR.Globals.is_authenticated && $.make('div', { className: 'NB-modal-submit-begin NB-modal-submit-button NB-modal-submit-grey NB-disabled' }, 'Loading Training...'))
|
|
])
|
|
])
|
|
]);
|
|
|
|
},
|
|
|
|
make_trainer_outro: function() {
|
|
var self = this;
|
|
|
|
this.$modal = $.make('div', { className: 'NB-modal-classifiers NB-modal NB-modal-trainer'}, [
|
|
$.make('h2', { className: 'NB-modal-title' }, 'Congratulations! You\'re done.'),
|
|
$.make('h3', { className: 'NB-modal-subtitle' }, 'Here\'s what happens next:'),
|
|
$.make('ol', { className: 'NB-trainer-points' }, [
|
|
$.make('li', [
|
|
$.make('img', { src: NEWSBLUR.Globals.MEDIA_URL + '/img/reader/sample_classifier_tag.png', style: 'float: right', width: 135 }),
|
|
$.make('b', 'You can change your opinions.'),
|
|
' You can click the ',
|
|
$.make('img', { src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/thumbs-up.svg', style: 'vertical-align: middle;padding: 0 8px 0 2px', width: 14, height: 20 }),
|
|
$.make('img', { src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/thumbs-down.svg', style: 'vertical-align: top; padding: 0', width: 14, height: 20 }),
|
|
' buttons next to stories as you read them.'
|
|
]),
|
|
$.make('li', [
|
|
$.make('img', { src: NEWSBLUR.Globals.MEDIA_URL + '/img/reader/intelligence_slider_positive.png', style: 'float: right', width: 114, height: 29 }),
|
|
$.make('b', 'As a reminder, use the intelligence slider to select a filter:'),
|
|
$.make('img', { className: 'NB-trainer-bullet', src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/indicator-hidden.svg'}),
|
|
' are stories you don\'t like',
|
|
$.make('br'),
|
|
$.make('img', { className: 'NB-trainer-bullet', src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/indicator-unread.svg'}),
|
|
' are stories you have not yet rated',
|
|
$.make('br'),
|
|
$.make('img', { className: 'NB-trainer-bullet', src: NEWSBLUR.Globals.MEDIA_URL + '/img/icons/nouns/indicator-focus.svg'}),
|
|
' are stories you like'
|
|
|
|
]),
|
|
$.make('li', [
|
|
$.make('b', 'You can also filter out stories you don\'t want to read.'),
|
|
' As great as finding good stuff is, you can just as easily ignore the stories you do not like.'
|
|
])
|
|
]),
|
|
$.make('div', { className: 'NB-modal-submit-bottom' }, [
|
|
$.make('div', { className: 'NB-modal-submit' }, [
|
|
$.make('div', { className: 'NB-modal-submit-button NB-modal-submit-reset' }, $.entity('«') + ' Retrain all sites'),
|
|
$.make('div', { className: 'NB-modal-submit-end NB-modal-submit-button' }, 'Close Training and Start Reading')
|
|
])
|
|
])
|
|
]);
|
|
|
|
},
|
|
|
|
make_modal_feed: function() {
|
|
var self = this;
|
|
var feed = this.feed;
|
|
|
|
// NEWSBLUR.log(['Make feed', feed, this.feed_authors, this.feed_tags, this.options['feed_loaded']]);
|
|
|
|
this.$modal = $.make('div', { className: 'NB-modal-classifiers NB-modal ' + (this.options['training'] && 'NB-modal-trainer') }, [
|
|
$.make('div', { className: 'NB-modal-loading' }),
|
|
$.make('h2', { className: 'NB-modal-title' }, ''),
|
|
$.make('h2', { className: 'NB-modal-subtitle' }, [
|
|
(this.options['training'] && $.make('div', { className: 'NB-classifier-trainer-counts' })),
|
|
$.make('img', { className: 'NB-modal-feed-image feed_favicon', src: $.favicon(this.feed) }),
|
|
$.make('div', { className: 'NB-modal-feed-heading' }, [
|
|
$.make('span', { className: 'NB-modal-feed-title' }, this.feed.get('feed_title')),
|
|
$.make('span', { className: 'NB-modal-feed-subscribers' }, Inflector.pluralize(' subscriber', this.feed.get('num_subscribers'), true))
|
|
])
|
|
]),
|
|
(this.options['feed_loaded'] &&
|
|
$.make('form', { method: 'post', className: 'NB-publisher' }, [
|
|
(!_.isEmpty(this.user_classifiers.titles) && $.make('div', { className: 'NB-modal-field NB-fieldset NB-classifiers' }, [
|
|
$.make('h5', 'Titles and Phrases'),
|
|
$.make('div', { className: 'NB-classifier-titles NB-fieldset-fields NB-classifiers' },
|
|
this.make_user_titles()
|
|
)
|
|
])),
|
|
(this.feed_authors.length && $.make('div', { className: 'NB-modal-field NB-fieldset NB-classifiers' }, [
|
|
$.make('h5', 'Authors'),
|
|
$.make('div', { className: 'NB-classifier-authors NB-fieldset-fields NB-classifiers' },
|
|
this.make_authors(this.feed_authors).concat(this.make_user_authors())
|
|
)
|
|
])),
|
|
(this.feed_tags.length && $.make('div', { className: 'NB-modal-field NB-fieldset NB-classifiers' }, [
|
|
$.make('h5', 'Categories & Tags'),
|
|
$.make('div', { className: 'NB-classifier-tags NB-fieldset-fields NB-classifiers' },
|
|
this.make_tags(this.feed_tags).concat(this.make_user_tags())
|
|
)
|
|
])),
|
|
(this.feed_publishers && this.feed_publishers.length && $.make('div', { className: 'NB-modal-field NB-fieldset NB-publishers' }, [
|
|
$.make('h5', 'Sharing Stories From These Sites'),
|
|
$.make('div', { className: 'NB-classifier-publishers NB-fieldset-fields NB-classifiers' },
|
|
this.make_publishers(this.feed_publishers)
|
|
)
|
|
])),
|
|
$.make('div', { className: 'NB-modal-field NB-fieldset NB-classifiers' }, [
|
|
$.make('h5', 'Everything by This Publisher'),
|
|
$.make('div', { className: 'NB-fieldset-fields NB-classifiers' },
|
|
this.make_publisher(feed)
|
|
)
|
|
])
|
|
])
|
|
),
|
|
(!this.options['feed_loaded'] &&
|
|
$.make('form', { method: 'post', className: 'NB-publisher' })),
|
|
(this.options['training'] && $.make('div', { className: 'NB-modal-submit-bottom' }, [
|
|
$.make('div', { className: 'NB-modal-submit' }, [
|
|
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
|
|
$.make('div', { className: 'NB-modal-submit-button NB-modal-submit-back' }, $.entity('«') + ' Back'),
|
|
$.make('div', { className: 'NB-modal-submit-button NB-modal-submit-green NB-modal-submit-next NB-modal-submit-save' }, 'Save & Next '+$.entity('»')),
|
|
$.make('div', { className: 'NB-modal-submit-button NB-modal-submit-grey' }, 'Close')
|
|
])
|
|
])),
|
|
(!this.options['training'] && $.make('div', { className: 'NB-modal-submit-bottom' }, [
|
|
$.make('div', { className: 'NB-modal-submit' }, [
|
|
$.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }),
|
|
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
|
|
$.make('div', { className: 'NB-modal-submit-save NB-modal-submit-button NB-modal-submit-green NB-disabled' }, 'Check what you like above...')
|
|
])
|
|
]))
|
|
]);
|
|
},
|
|
|
|
make_modal_story: function() {
|
|
var self = this;
|
|
var story = this.story;
|
|
var feed = this.feed;
|
|
|
|
// NEWSBLUR.log(['Make Story', story, feed]);
|
|
|
|
// HTML entities decoding.
|
|
var story_title = _.string.trim($('<div/>').html(story.get('story_title')).text());
|
|
|
|
this.$modal = $.make('div', { className: 'NB-modal-classifiers NB-modal' }, [
|
|
$.make('div', { className: 'NB-modal-loading' }),
|
|
$.make('h2', { className: 'NB-modal-title' }),
|
|
$.make('h2', { className: 'NB-modal-subtitle' }, [
|
|
(this.options['training'] && $.make('div', { className: 'NB-classifier-trainer-counts' })),
|
|
$.make('img', { className: 'NB-modal-feed-image feed_favicon', src: $.favicon(this.feed) }),
|
|
$.make('div', { className: 'NB-modal-feed-heading' }, [
|
|
$.make('span', { className: 'NB-modal-feed-title' }, this.feed.get('feed_title')),
|
|
$.make('span', { className: 'NB-modal-feed-subscribers' }, Inflector.pluralize(' subscriber', this.feed.get('num_subscribers'), true))
|
|
])
|
|
]),
|
|
(this.options['feed_loaded'] &&
|
|
$.make('form', { method: 'post' }, [
|
|
(story_title && $.make('div', { className: 'NB-modal-field NB-fieldset' }, [
|
|
$.make('h5', 'Story Title'),
|
|
$.make('div', { className: 'NB-fieldset-fields NB-classifiers' }, [
|
|
$.make('input', { type: 'text', value: story_title, className: 'NB-classifier-title-highlight' }),
|
|
this.make_classifier('<span class="NB-classifier-title-placeholder">Highlight phrases to look for in future stories</span>', '', 'title'),
|
|
$.make('span',
|
|
this.make_user_titles(story_title)
|
|
)
|
|
])
|
|
])),
|
|
(story.story_authors() && $.make('div', { className: 'NB-modal-field NB-fieldset' }, [
|
|
$.make('h5', 'Story Author'),
|
|
$.make('div', { className: 'NB-fieldset-fields NB-classifiers' },
|
|
this.make_authors([story.story_authors()])
|
|
)
|
|
])),
|
|
(story.get('story_tags').length && $.make('div', { className: 'NB-modal-field NB-fieldset' }, [
|
|
$.make('h5', 'Story Categories & Tags'),
|
|
$.make('div', { className: 'NB-classifier-tags NB-fieldset-fields NB-classifiers' },
|
|
this.make_tags(story.get('story_tags'))
|
|
)
|
|
])),
|
|
|
|
(this.feed_publishers && this.feed_publishers.length && $.make('div', { className: 'NB-modal-field NB-fieldset NB-publishers' }, [
|
|
$.make('h5', 'Sharing Stories From These Sites'),
|
|
$.make('div', { className: 'NB-classifier-publishers NB-fieldset-fields NB-classifiers' },
|
|
this.make_publishers(this.feed_publishers)
|
|
)
|
|
])),
|
|
$.make('div', { className: 'NB-modal-field NB-fieldset' }, [
|
|
$.make('h5', 'Everything by This Publisher'),
|
|
$.make('div', { className: 'NB-fieldset-fields NB-classifiers' },
|
|
this.make_publisher(feed)
|
|
)
|
|
])
|
|
])
|
|
),
|
|
(!this.options['feed_loaded'] &&
|
|
$.make('form', { method: 'post', className: 'NB-publisher' })),
|
|
$.make('div', { className: 'NB-modal-submit-bottom' }, [
|
|
$.make('div', { className: 'NB-modal-submit' }, [
|
|
$.make('input', { name: 'story_id', value: this.story_id, type: 'hidden' }),
|
|
$.make('input', { name: 'feed_id', value: this.feed_id, type: 'hidden' }),
|
|
$.make('div', { className: 'NB-modal-submit-save NB-modal-submit-button NB-modal-submit-green NB-disabled' }, 'Check what you like above...')
|
|
])
|
|
])
|
|
]);
|
|
},
|
|
|
|
make_modal_title: function() {
|
|
var $modal_title = $('.NB-modal-title', this.$modal);
|
|
|
|
var $title = $.make('div', [
|
|
'What do you ',
|
|
$.make('b', { className: 'NB-classifier-title-like' }, 'like'),
|
|
' and ',
|
|
$.make('b', { className: 'NB-classifier-title-dislike' }, 'dislike'),
|
|
' about this ',
|
|
(this.flags['publisher'] && 'site'),
|
|
(this.flags['story'] && 'story'),
|
|
'?'
|
|
]);
|
|
|
|
$modal_title.html($title);
|
|
},
|
|
|
|
make_modal_trainer_count: function() {
|
|
var $count = $('.NB-classifier-trainer-counts', this.$modal);
|
|
var count = this.trainer_iterator + 1;
|
|
var total = this.trainer_data.length;
|
|
$count.html(count + '/' + total);
|
|
},
|
|
|
|
make_user_titles: function(existing_title) {
|
|
var $titles = [];
|
|
var titles = _.keys(this.user_classifiers.titles);
|
|
|
|
_.each(titles, _.bind(function(title) {
|
|
if (!existing_title || existing_title.toLowerCase().indexOf(title.toLowerCase()) != -1) {
|
|
var $title = this.make_classifier(title, title, 'title');
|
|
$titles.push($title);
|
|
}
|
|
}, this));
|
|
|
|
return $titles;
|
|
},
|
|
|
|
make_authors: function(authors) {
|
|
var $authors = [];
|
|
|
|
for (var a in authors) {
|
|
var author_obj = authors[a];
|
|
if (typeof author_obj == 'string') {
|
|
var author = author_obj;
|
|
var author_count;
|
|
} else {
|
|
var author = author_obj[0];
|
|
var author_count = author_obj[1];
|
|
}
|
|
|
|
if (!author) continue;
|
|
|
|
var $author = this.make_classifier(author, author, 'author', author_count);
|
|
$authors.push($author);
|
|
}
|
|
return $authors;
|
|
},
|
|
|
|
make_user_authors: function() {
|
|
var $authors = [];
|
|
var user_authors = _.keys(this.user_classifiers.authors);
|
|
var feed_authors = _.map(this.feed_authors, function(author) { return author[0]; });
|
|
var authors = _.reduce(user_authors, function(memo, author, i) {
|
|
if (!_.contains(feed_authors, author)) return memo.concat(author);
|
|
return memo;
|
|
}, []);
|
|
|
|
return this.make_authors(authors);
|
|
},
|
|
|
|
make_tags: function(tags) {
|
|
var $tags = [];
|
|
|
|
for (var t in tags) {
|
|
var tag_obj = tags[t];
|
|
if (typeof tag_obj == 'string') {
|
|
var tag = tag_obj;
|
|
var tag_count;
|
|
} else {
|
|
var tag = tag_obj[0];
|
|
var tag_count = tag_obj[1];
|
|
}
|
|
|
|
if (!tag) continue;
|
|
|
|
var $tag = this.make_classifier(tag, tag, 'tag', tag_count);
|
|
$tags.push($tag);
|
|
}
|
|
|
|
return $tags;
|
|
},
|
|
|
|
make_user_tags: function() {
|
|
var $tags = [];
|
|
var user_tags = _.keys(this.user_classifiers.tags);
|
|
var feed_tags = _.map(this.feed_tags, function(tag) { return tag[0]; });
|
|
var tags = _.reduce(user_tags, function(memo, tag, i) {
|
|
if (!_.contains(feed_tags, tag)) return memo.concat(tag);
|
|
return memo;
|
|
}, []);
|
|
|
|
return this.make_tags(tags);
|
|
},
|
|
|
|
make_publishers: function(publishers) {
|
|
var $publishers = publishers.map(_.bind(function(publisher) {
|
|
return this.make_publisher(publisher);
|
|
}, this));
|
|
|
|
return $publishers;
|
|
},
|
|
|
|
make_publisher: function(publisher) {
|
|
var $publisher = this.make_classifier(_.string.truncate(publisher.get('feed_title'), 50),
|
|
publisher.id, 'feed', publisher.get('story_count'), publisher);
|
|
return $publisher;
|
|
},
|
|
|
|
make_classifier: function(classifier_title, classifier_value, classifier_type, classifier_count, classifier) {
|
|
var score = 0;
|
|
// NEWSBLUR.log(['classifiers', this.user_classifiers, classifier_value, this.user_classifiers[classifier_type+'s']]);
|
|
if (this.user_classifiers[classifier_type+'s'] &&
|
|
classifier_value in this.user_classifiers[classifier_type+'s']) {
|
|
score = this.user_classifiers[classifier_type+'s'][classifier_value];
|
|
}
|
|
|
|
var classifier_type_title = Inflector.capitalize(classifier_type=='feed' ?
|
|
'site' :
|
|
classifier_type);
|
|
|
|
var $classifier = $.make('span', { className: 'NB-classifier-container' }, [
|
|
$.make('span', { className: 'NB-classifier NB-classifier-'+classifier_type }, [
|
|
$.make('input', {
|
|
type: 'checkbox',
|
|
className: 'NB-classifier-input-like',
|
|
name: 'like_'+classifier_type,
|
|
value: classifier_value
|
|
}),
|
|
$.make('input', {
|
|
type: 'checkbox',
|
|
className: 'NB-classifier-input-dislike',
|
|
name: 'dislike_'+classifier_type,
|
|
value: classifier_value
|
|
}),
|
|
$.make('div', { className: 'NB-classifier-icon-like' }),
|
|
$.make('div', { className: 'NB-classifier-icon-dislike' }, [
|
|
$.make('div', { className: 'NB-classifier-icon-dislike-inner' })
|
|
]),
|
|
$.make('label', [
|
|
(classifier_type == 'feed' &&
|
|
$.make('img', {
|
|
className: 'feed_favicon',
|
|
src: $.favicon(classifier)
|
|
})),
|
|
$.make('b', classifier_type_title+': '),
|
|
$.make('span', classifier_title)
|
|
])
|
|
]),
|
|
(classifier_count && $.make('span', { className: 'NB-classifier-count' }, [
|
|
'× ',
|
|
classifier_count
|
|
]))
|
|
]);
|
|
|
|
if (score > 0) {
|
|
$('.NB-classifier', $classifier).addClass('NB-classifier-like');
|
|
$('.NB-classifier-input-like', $classifier).prop('checked', true);
|
|
} else if (score < 0) {
|
|
$('.NB-classifier', $classifier).addClass('NB-classifier-dislike');
|
|
$('.NB-classifier-input-dislike', $classifier).prop('checked', true);
|
|
}
|
|
|
|
$('.NB-classifier', $classifier).bind('mouseenter', function(e) {
|
|
$(e.currentTarget).addClass('NB-classifier-hover-like');
|
|
}).bind('mouseleave', function(e) {
|
|
$(e.currentTarget).removeClass('NB-classifier-hover-like');
|
|
});
|
|
|
|
$('.NB-classifier-icon-dislike', $classifier).bind('mouseenter', function(e) {
|
|
$('.NB-classifier', $classifier).addClass('NB-classifier-hover-dislike');
|
|
}).bind('mouseleave', function(e) {
|
|
$('.NB-classifier', $classifier).removeClass('NB-classifier-hover-dislike');
|
|
});
|
|
|
|
return $classifier;
|
|
},
|
|
|
|
change_classifier: function($classifier, classifier_opinion) {
|
|
var $like = $('.NB-classifier-input-like', $classifier);
|
|
var $dislike = $('.NB-classifier-input-dislike', $classifier);
|
|
|
|
var $save = $('.NB-modal-submit-save', this.$modal);
|
|
var $close = $('.NB-modal-submit-grey', this.$modal);
|
|
var $back = $('.NB-modal-submit-back', this.$modal);
|
|
|
|
if (classifier_opinion == 'like') {
|
|
if ($classifier.is('.NB-classifier-like')) {
|
|
$classifier.removeClass('NB-classifier-like');
|
|
$dislike.prop('checked', false);
|
|
$like.prop('checked', false);
|
|
} else {
|
|
$classifier.removeClass('NB-classifier-dislike');
|
|
$classifier.addClass('NB-classifier-like');
|
|
$dislike.prop('checked', false);
|
|
$like.prop('checked', true);
|
|
}
|
|
} else if (classifier_opinion == 'dislike') {
|
|
if ($classifier.is('.NB-classifier-dislike')) {
|
|
$classifier.removeClass('NB-classifier-dislike');
|
|
$like.prop('checked', false);
|
|
$dislike.prop('checked', false);
|
|
} else {
|
|
$classifier.removeClass('NB-classifier-like');
|
|
$classifier.addClass('NB-classifier-dislike');
|
|
$like.prop('checked', false);
|
|
$dislike.prop('checked', true);
|
|
}
|
|
}
|
|
|
|
if (this.options['training']) {
|
|
$close.text('Save & Close');
|
|
} else {
|
|
$save.removeClass("NB-disabled").text('Save Training');
|
|
}
|
|
// NEWSBLUR.log(['change_classifier', classifier_opinion, $classifier, $like.is(':checked'), $dislike.is(':checked')]);
|
|
},
|
|
|
|
end: function() {
|
|
this.model.preference('has_trained_intelligence', true);
|
|
NEWSBLUR.reader.check_hide_getting_started();
|
|
$.modal.close();
|
|
},
|
|
|
|
// ==========
|
|
// = Events =
|
|
// ==========
|
|
|
|
handle_text_highlight: function() {
|
|
var self = this;
|
|
var $title_highlight = $('.NB-classifier-title-highlight', this.$modal);
|
|
var $title_placeholder = $('.NB-classifier-title-placeholder', this.$modal);
|
|
var $title_classifier = $title_placeholder.parents('.NB-classifier').eq(0);
|
|
var $title_checkboxs = $('.NB-classifier-input-like, .NB-classifier-input-dislike', $title_classifier);
|
|
|
|
var update = function() {
|
|
var text = $.trim($(this).getSelection().text);
|
|
|
|
if (text.length && $title_placeholder.text() != text) {
|
|
$title_placeholder.text(text);
|
|
$title_checkboxs.val(text);
|
|
if (!$title_classifier.is('.NB-classifier-like,.NB-classifier-dislike')) {
|
|
self.change_classifier($title_classifier, 'like');
|
|
}
|
|
}
|
|
};
|
|
|
|
$title_highlight
|
|
.keydown(update).keyup(update)
|
|
.mousedown(update).mouseup(update).mousemove(update);
|
|
$title_checkboxs.val($title_highlight.val());
|
|
|
|
$title_placeholder.parents('.NB-classifier').bind('click', function() {
|
|
if ($title_highlight.val() == $title_checkboxs.val()) {
|
|
$title_placeholder.text($title_highlight.val());
|
|
}
|
|
});
|
|
},
|
|
|
|
handle_cancel: function() {
|
|
var $cancel = $('.NB-modal-cancel', this.$modal);
|
|
|
|
$cancel.click(function(e) {
|
|
e.preventDefault();
|
|
$.modal.close();
|
|
});
|
|
},
|
|
|
|
handle_clicks: function(elem, e) {
|
|
var self = this;
|
|
|
|
if (this.options['training']) {
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-begin' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.load_next_feed_in_trainer();
|
|
});
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-save.NB-modal-submit-next' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.save(true);
|
|
self.load_next_feed_in_trainer();
|
|
});
|
|
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-back' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.load_previous_feed_in_trainer();
|
|
});
|
|
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-reset' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.retrain_all_sites();
|
|
});
|
|
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-grey' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.save();
|
|
});
|
|
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-end' }, function($t, $p){
|
|
e.preventDefault();
|
|
NEWSBLUR.reader.force_feed_refresh();
|
|
self.end();
|
|
// NEWSBLUR.reader.open_feed(self.feed_id, true);
|
|
// TODO: Update counts in active feed.
|
|
});
|
|
} else {
|
|
$.targetIs(e, { tagSelector: '.NB-modal-submit-save:not(.NB-modal-submit-next)' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.save();
|
|
return false;
|
|
});
|
|
}
|
|
|
|
var stop = false;
|
|
$.targetIs(e, { tagSelector: '.NB-classifier-icon-dislike' }, function($t, $p){
|
|
e.preventDefault();
|
|
stop = true;
|
|
self.change_classifier($t.closest('.NB-classifier'), 'dislike');
|
|
});
|
|
if (stop) return;
|
|
$.targetIs(e, { tagSelector: '.NB-classifier' }, function($t, $p){
|
|
e.preventDefault();
|
|
self.change_classifier($t, 'like');
|
|
});
|
|
},
|
|
|
|
serialize_classifier: function() {
|
|
var data = {};
|
|
$('.NB-classifier', this.$modal).each(function() {
|
|
var value = $('.NB-classifier-input-like', this).val();
|
|
if ($('.NB-classifier-input-like, .NB-classifier-input-dislike', this).is(':checked')) {
|
|
var name = $('input:checked', this).attr('name');
|
|
if (!data[name]) data[name] = [];
|
|
data[name].push(value);
|
|
} else {
|
|
var name = 'remove_'+$('.NB-classifier-input-like', this).attr('name');
|
|
if (!data[name]) data[name] = [];
|
|
data[name].push(value);
|
|
}
|
|
});
|
|
|
|
data['feed_id'] = this.feed_id;
|
|
if (this.story_id) {
|
|
data['story_id'] = this.story_id;
|
|
}
|
|
return data;
|
|
},
|
|
|
|
save: function(keep_modal_open) {
|
|
var self = this;
|
|
var $save = $('.NB-modal-submit-save', this.$modal);
|
|
var data = this.serialize_classifier();
|
|
var feed_id = this.feed_id;
|
|
if (this.options.social_feed && this.story_id) {
|
|
feed_id = this.original_feed_id;
|
|
}
|
|
|
|
if (this.options['training']) {
|
|
this.cache[this.feed_id] = this.$modal.clone();
|
|
}
|
|
$save.text('Saving...');
|
|
$save.addClass('NB-disabled');
|
|
|
|
this.update_opinions();
|
|
NEWSBLUR.assets.recalculate_story_scores(feed_id);
|
|
NEWSBLUR.assets.stories.trigger('render:intelligence');
|
|
this.model.save_classifier(data, function() {
|
|
if (!keep_modal_open) {
|
|
NEWSBLUR.reader.feed_unread_count(feed_id);
|
|
$.modal.close();
|
|
}
|
|
});
|
|
},
|
|
|
|
update_opinions: function() {
|
|
var self = this;
|
|
var feed_id = this.feed_id;
|
|
|
|
$('input[type=checkbox]', this.$modal).each(function() {
|
|
var $this = $(this);
|
|
var name = $this.attr('name').replace(/^(dis)?like_/, '');
|
|
var score = /^dislike/.test($this.attr('name')) ? -1 : 1;
|
|
var value = $this.val();
|
|
var checked = $this.prop('checked');
|
|
|
|
if (checked) {
|
|
if (name == 'tag') {
|
|
self.model.classifiers[feed_id].tags[value] = score;
|
|
} else if (name == 'title') {
|
|
self.model.classifiers[feed_id].titles[value] = score;
|
|
} else if (name == 'author') {
|
|
self.model.classifiers[feed_id].authors[value] = score;
|
|
} else if (name == 'feed') {
|
|
self.model.classifiers[feed_id].feeds[feed_id] = score;
|
|
}
|
|
} else {
|
|
if (name == 'tag' && self.model.classifiers[feed_id].tags[value] == score) {
|
|
delete self.model.classifiers[feed_id].tags[value];
|
|
} else if (name == 'title' && self.model.classifiers[feed_id].titles[value] == score) {
|
|
delete self.model.classifiers[feed_id].titles[value];
|
|
} else if (name == 'author' && self.model.classifiers[feed_id].authors[value] == score) {
|
|
delete self.model.classifiers[feed_id].authors[value];
|
|
} else if (name == 'feed' && self.model.classifiers[feed_id].feeds[feed_id] == score) {
|
|
delete self.model.classifiers[feed_id].feeds[feed_id];
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
};
|
|
|
|
NEWSBLUR.ReaderClassifierStory.prototype = new NEWSBLUR.Modal;
|
|
NEWSBLUR.ReaderClassifierStory.prototype.constructor = NEWSBLUR.ReaderClassifierStory;
|
|
_.extend(NEWSBLUR.ReaderClassifierStory.prototype, classifier_prototype);
|
|
|
|
NEWSBLUR.ReaderClassifierFeed.prototype = new NEWSBLUR.Modal;
|
|
NEWSBLUR.ReaderClassifierFeed.prototype.constructor = NEWSBLUR.ReaderClassifierFeed;
|
|
_.extend(NEWSBLUR.ReaderClassifierFeed.prototype, classifier_prototype);
|
|
|
|
NEWSBLUR.ReaderClassifierTrainer.prototype = new NEWSBLUR.Modal;
|
|
NEWSBLUR.ReaderClassifierTrainer.prototype.constructor = NEWSBLUR.ReaderClassifierTrainer;
|
|
_.extend(NEWSBLUR.ReaderClassifierTrainer.prototype, classifier_prototype);
|