2013-08-29 10:29:56 +00:00
|
|
|
(function () {
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var website = openerp.website;
|
2013-09-05 09:20:38 +00:00
|
|
|
website.templates.push('/website/static/src/xml/website.seo.xml');
|
|
|
|
|
2013-08-29 10:29:56 +00:00
|
|
|
website.EditorBar.include({
|
|
|
|
events: _.extend({}, website.EditorBar.prototype.events, {
|
|
|
|
'click a[data-action=promote-current-page]': 'promotePage',
|
|
|
|
}),
|
|
|
|
promotePage: function () {
|
|
|
|
(new website.seo.Configurator()).appendTo($(document.body));
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
website.seo = {};
|
2013-08-29 16:39:52 +00:00
|
|
|
|
2013-09-12 15:46:20 +00:00
|
|
|
website.seo.Suggestion = openerp.Widget.extend({
|
|
|
|
template: 'website.seo_suggestion',
|
2013-09-12 16:08:55 +00:00
|
|
|
events: {
|
|
|
|
'click .js_seo_suggestion': 'select',
|
|
|
|
},
|
2013-09-12 15:46:20 +00:00
|
|
|
init: function (parent, keyword) {
|
|
|
|
this.keyword = keyword;
|
|
|
|
// cf. http://getbootstrap.com/components/#labels
|
|
|
|
// default, primary, success, info, warning, danger
|
|
|
|
this.type = 'default';
|
|
|
|
this._super(parent);
|
2013-09-03 15:41:44 +00:00
|
|
|
},
|
2013-09-12 16:08:55 +00:00
|
|
|
select: function () {
|
|
|
|
this.trigger('selected', this.keyword);
|
|
|
|
},
|
2013-09-03 14:51:32 +00:00
|
|
|
});
|
|
|
|
|
2013-09-12 15:46:20 +00:00
|
|
|
website.seo.SuggestionList = openerp.Widget.extend({
|
|
|
|
template: 'website.seo_list',
|
|
|
|
init: function (parent, word) {
|
|
|
|
this.word = word;
|
2013-09-02 09:37:55 +00:00
|
|
|
this._super(parent);
|
2013-09-03 15:41:44 +00:00
|
|
|
},
|
2013-09-12 15:46:20 +00:00
|
|
|
start: function () {
|
|
|
|
this.refresh();
|
|
|
|
},
|
|
|
|
refresh: function () {
|
|
|
|
var self = this;
|
|
|
|
self.$el.append("Loading...");
|
|
|
|
function addSuggestions (list) {
|
|
|
|
self.$el.empty();
|
|
|
|
// TODO Improve algorithm + Ajust based on custom user keywords
|
|
|
|
var nameRegex = new RegExp(self.companyName, "gi");
|
|
|
|
var cleanList = _.map(list, function removeCompanyName (word) {
|
|
|
|
return word.replace(nameRegex, "").trim();
|
|
|
|
});
|
|
|
|
// TODO Order properly ?
|
|
|
|
_.each(_.uniq(cleanList), function (keyword) {
|
|
|
|
if (keyword) {
|
|
|
|
var suggestion = new website.seo.Suggestion(self, keyword);
|
2013-09-12 16:08:55 +00:00
|
|
|
suggestion.on('selected', self, function (word) {
|
|
|
|
self.trigger('selected', word);
|
|
|
|
});
|
2013-09-12 15:46:20 +00:00
|
|
|
suggestion.appendTo(self.$el);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
$.getJSON("http://seo.eu01.aws.af.cm/suggest/"+encodeURIComponent(this.word + " "), addSuggestions);
|
|
|
|
},
|
2013-08-29 16:39:52 +00:00
|
|
|
});
|
|
|
|
|
2013-08-29 10:29:56 +00:00
|
|
|
website.seo.Keyword = openerp.Widget.extend({
|
|
|
|
template: 'website.seo_keyword',
|
|
|
|
events: {
|
|
|
|
'click a[data-action=remove-keyword]': 'destroy',
|
|
|
|
},
|
2013-09-04 04:07:00 +00:00
|
|
|
maxWordsPerKeyword: 4, // TODO Check
|
2013-09-12 15:46:20 +00:00
|
|
|
init: function (parent, keyword) {
|
|
|
|
this.keyword = keyword;
|
2013-09-04 04:07:00 +00:00
|
|
|
// cf. http://getbootstrap.com/components/#labels
|
|
|
|
// default, primary, success, info, warning, danger
|
2013-09-12 15:46:20 +00:00
|
|
|
this.type = 'warning';
|
2013-09-02 09:37:55 +00:00
|
|
|
this._super(parent);
|
2013-08-29 10:29:56 +00:00
|
|
|
},
|
2013-09-12 15:33:38 +00:00
|
|
|
start: function () {
|
2013-09-12 16:08:55 +00:00
|
|
|
var self = this;
|
|
|
|
self.suggestionList = new website.seo.SuggestionList(self, this.keyword);
|
|
|
|
self.suggestionList.on('selected', self, function (word) {
|
|
|
|
self.trigger('selected', word);
|
|
|
|
});
|
2013-09-12 15:33:38 +00:00
|
|
|
this.suggestionList.appendTo(this.$('.js_seo_keyword_suggestion'));
|
|
|
|
},
|
2013-08-29 10:29:56 +00:00
|
|
|
destroy: function () {
|
2013-09-03 15:41:44 +00:00
|
|
|
this.trigger('removed');
|
2013-08-29 10:29:56 +00:00
|
|
|
this._super();
|
|
|
|
},
|
|
|
|
});
|
2013-08-29 16:39:52 +00:00
|
|
|
|
2013-09-03 15:41:44 +00:00
|
|
|
website.seo.KeywordList = openerp.Widget.extend({
|
2013-09-04 04:07:00 +00:00
|
|
|
template: 'website.seo_list',
|
2013-09-03 15:41:44 +00:00
|
|
|
maxKeywords: 10,
|
2013-09-03 14:51:32 +00:00
|
|
|
keywords: function () {
|
2013-09-04 04:07:00 +00:00
|
|
|
var result = [];
|
2013-09-12 16:08:55 +00:00
|
|
|
this.$('span.js_seo_keyword').each(function () {
|
2013-09-04 04:07:00 +00:00
|
|
|
result.push($(this).data('keyword'));
|
2013-09-03 14:51:32 +00:00
|
|
|
});
|
2013-09-04 04:07:00 +00:00
|
|
|
return result;
|
2013-09-03 14:51:32 +00:00
|
|
|
},
|
|
|
|
isKeywordListFull: function () {
|
2013-09-03 15:41:44 +00:00
|
|
|
return this.keywords().length >= this.maxKeywords;
|
2013-09-03 14:51:32 +00:00
|
|
|
},
|
|
|
|
isExistingKeyword: function (word) {
|
|
|
|
return _.contains(this.keywords(), word);
|
|
|
|
},
|
2013-09-12 16:08:55 +00:00
|
|
|
add: function (candidate) {
|
2013-09-03 15:41:44 +00:00
|
|
|
var self = this;
|
2013-09-04 04:07:00 +00:00
|
|
|
// TODO Refine
|
|
|
|
var word = candidate ? candidate.replace(/[,;.:<>]+/g, " ").replace(/ +/g, " ").trim() : "";
|
2013-09-12 10:34:09 +00:00
|
|
|
if (word && !self.isKeywordListFull() && !self.isExistingKeyword(word)) {
|
2013-09-12 15:46:20 +00:00
|
|
|
var keyword = new website.seo.Keyword(self, word);
|
2013-09-12 16:08:55 +00:00
|
|
|
keyword.on('removed', self, function () {
|
2013-09-03 15:41:44 +00:00
|
|
|
self.trigger('list-not-full');
|
2013-09-12 12:47:06 +00:00
|
|
|
self.trigger('removed', word);
|
2013-09-03 15:41:44 +00:00
|
|
|
});
|
2013-09-12 16:08:55 +00:00
|
|
|
keyword.on('selected', self, function (word) {
|
|
|
|
self.trigger('selected', word);
|
|
|
|
});
|
2013-09-12 10:34:09 +00:00
|
|
|
keyword.appendTo(self.$el);
|
2013-09-03 14:51:32 +00:00
|
|
|
}
|
2013-09-12 10:34:09 +00:00
|
|
|
if (self.isKeywordListFull()) {
|
2013-09-03 15:41:44 +00:00
|
|
|
self.trigger('list-full');
|
2013-09-03 14:51:32 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2013-09-02 15:06:29 +00:00
|
|
|
website.seo.Image = openerp.Widget.extend({
|
|
|
|
template: 'website.seo_image',
|
|
|
|
init: function (parent, options) {
|
|
|
|
this.src = options.src;
|
|
|
|
this.alt = options.alt;
|
|
|
|
this._super(parent);
|
2013-09-04 04:07:00 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
website.seo.ImageList = openerp.Widget.extend({
|
|
|
|
start: function () {
|
|
|
|
var self = this;
|
|
|
|
new website.seo.PageParser().images().each(function (index, image) {
|
|
|
|
new website.seo.Image(self, image).appendTo(self.$el);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
images: function () {
|
|
|
|
var result = [];
|
2013-09-12 10:34:09 +00:00
|
|
|
this.$('input').each(function () {
|
2013-09-04 04:07:00 +00:00
|
|
|
var $input = $(this);
|
|
|
|
result.push({
|
|
|
|
src: $input.attr('src'),
|
|
|
|
alt: $input.val(),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
add: function (image) {
|
|
|
|
new website.seo.Image(this, image).appendTo(this.$el);
|
|
|
|
},
|
2013-09-02 15:06:29 +00:00
|
|
|
});
|
|
|
|
|
2013-09-12 15:46:20 +00:00
|
|
|
website.seo.PageParser = openerp.Class.extend({
|
|
|
|
url: function () {
|
|
|
|
var url = window.location.href;
|
|
|
|
var hashIndex = url.indexOf('#');
|
|
|
|
return hashIndex >= 0 ? url.substring(0, hashIndex) : url;
|
|
|
|
},
|
|
|
|
title: function () {
|
|
|
|
return $(document.title).text();
|
|
|
|
},
|
|
|
|
headers: function (tag) {
|
|
|
|
return $('#wrap '+tag).map(function () {
|
|
|
|
return $(this).text();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
images: function () {
|
|
|
|
return $('#wrap img').map(function () {
|
|
|
|
var $img = $(this);
|
|
|
|
return {
|
|
|
|
src: $img.attr('src'),
|
|
|
|
alt: $img.attr('alt'),
|
|
|
|
};
|
|
|
|
});
|
|
|
|
},
|
|
|
|
company: function () {
|
|
|
|
return $('meta[name="openerp.company"]').attr('value');
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
website.seo.Tip = openerp.Widget.extend({
|
|
|
|
template: 'website.seo_tip',
|
|
|
|
events: {
|
|
|
|
'closed.bs.alert': 'destroy',
|
|
|
|
},
|
|
|
|
init: function (parent, options) {
|
|
|
|
this.message = options.message;
|
|
|
|
// cf. http://getbootstrap.com/components/#alerts
|
|
|
|
// success, info, warning or danger
|
|
|
|
this.type = options.type || 'info';
|
|
|
|
this._super(parent);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2013-08-29 10:29:56 +00:00
|
|
|
website.seo.Configurator = openerp.Widget.extend({
|
|
|
|
template: 'website.seo_configuration',
|
|
|
|
events: {
|
|
|
|
'keypress input[name=seo_page_keywords]': 'confirmKeyword',
|
|
|
|
'click button[data-action=add]': 'addKeyword',
|
2013-09-04 04:07:00 +00:00
|
|
|
'click button[data-action=update]': 'update',
|
2013-08-30 13:19:52 +00:00
|
|
|
'hidden.bs.modal': 'destroy'
|
2013-08-29 10:29:56 +00:00
|
|
|
},
|
|
|
|
maxTitleSize: 65,
|
|
|
|
maxDescriptionSize: 155,
|
|
|
|
start: function () {
|
2013-09-12 10:34:09 +00:00
|
|
|
var self = this;
|
2013-09-12 16:08:55 +00:00
|
|
|
var $modal = self.$el;
|
2013-08-29 10:29:56 +00:00
|
|
|
var pageParser = new website.seo.PageParser();
|
2013-09-04 04:07:00 +00:00
|
|
|
$modal.find('.js_seo_page_url').text(pageParser.url());
|
|
|
|
$modal.find('input[name=seo_page_title]').val(pageParser.title());
|
2013-09-12 16:08:55 +00:00
|
|
|
self.suggestImprovements(pageParser);
|
|
|
|
self.imageList = new website.seo.ImageList(self);
|
|
|
|
self.imageList.appendTo($modal.find('.js_seo_image_list'));
|
|
|
|
self.keywordList = new website.seo.KeywordList(self);
|
|
|
|
self.keywordList.on('list-full', self, function () {
|
2013-09-03 15:41:44 +00:00
|
|
|
$modal.find('input[name=seo_page_keywords]')
|
|
|
|
.attr('readonly', "readonly")
|
|
|
|
.attr('placeholder', "Remove a keyword first");
|
|
|
|
$modal.find('button[data-action=add]')
|
|
|
|
.prop('disabled', true).addClass('disabled');
|
|
|
|
});
|
2013-09-12 16:08:55 +00:00
|
|
|
self.keywordList.on('list-not-full', self, function () {
|
2013-09-03 15:41:44 +00:00
|
|
|
$modal.find('input[name=seo_page_keywords]')
|
|
|
|
.removeAttr('readonly').attr('placeholder', "");
|
|
|
|
$modal.find('button[data-action=add]')
|
|
|
|
.prop('disabled', false).removeClass('disabled');
|
|
|
|
});
|
2013-09-12 16:08:55 +00:00
|
|
|
self.keywordList.on('selected', self, function (word) {
|
|
|
|
self.keywordList.add(word);
|
|
|
|
});
|
|
|
|
self.keywordList.appendTo($modal.find('.js_seo_keywords_list'));
|
2013-09-12 13:13:07 +00:00
|
|
|
var companyName = pageParser.company().toLowerCase();
|
2013-09-12 16:08:55 +00:00
|
|
|
self.addKeyword(companyName);
|
2013-09-04 04:07:00 +00:00
|
|
|
$modal.modal();
|
2013-08-29 10:29:56 +00:00
|
|
|
},
|
2013-09-04 04:07:00 +00:00
|
|
|
suggestImprovements: function (parser) {
|
2013-09-02 09:37:55 +00:00
|
|
|
var tips = [];
|
|
|
|
var self = this;
|
|
|
|
function displayTip(message, type) {
|
2013-09-12 15:33:38 +00:00
|
|
|
new website.seo.Tip(self, {
|
2013-09-02 09:37:55 +00:00
|
|
|
message: message,
|
2013-09-12 15:33:38 +00:00
|
|
|
type: type,
|
2013-09-12 10:34:09 +00:00
|
|
|
}).appendTo(self.$('.js_seo_tips'));
|
2013-09-02 09:37:55 +00:00
|
|
|
}
|
2013-08-29 16:39:52 +00:00
|
|
|
var pageParser = parser || new website.seo.PageParser();
|
2013-09-12 15:33:38 +00:00
|
|
|
if (pageParser.headers('h1').length === 0) {
|
2013-09-02 09:37:55 +00:00
|
|
|
tips.push({
|
|
|
|
type: 'warning',
|
2013-09-04 04:07:00 +00:00
|
|
|
message: "You don't have an <h1> tag on your page.",
|
2013-09-02 09:37:55 +00:00
|
|
|
});
|
|
|
|
}
|
2013-09-04 04:07:00 +00:00
|
|
|
if (pageParser.headers('h1').length > 1) {
|
2013-09-02 09:37:55 +00:00
|
|
|
tips.push({
|
|
|
|
type: 'warning',
|
2013-09-04 04:07:00 +00:00
|
|
|
message: "You have more than one <h1> tag on your page.",
|
2013-09-02 09:37:55 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
if (tips.length > 0) {
|
|
|
|
_.each(tips, function (tip) {
|
|
|
|
displayTip(tip.message, tip.type);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
displayTip("Your page makup is appropriate for search engines.", 'success');
|
2013-08-29 16:39:52 +00:00
|
|
|
}
|
|
|
|
},
|
2013-08-29 10:29:56 +00:00
|
|
|
confirmKeyword: function (e) {
|
|
|
|
if (e.keyCode == 13) {
|
2013-09-12 10:34:09 +00:00
|
|
|
this.addKeyword();
|
2013-08-29 10:29:56 +00:00
|
|
|
}
|
|
|
|
},
|
2013-09-04 04:07:00 +00:00
|
|
|
addKeyword: function (word) {
|
2013-09-12 10:34:09 +00:00
|
|
|
var $input = this.$('input[name=seo_page_keywords]');
|
2013-09-04 04:07:00 +00:00
|
|
|
var keyword = _.isString(word) ? word : $input.val();
|
2013-09-12 16:08:55 +00:00
|
|
|
this.keywordList.add(keyword);
|
2013-09-04 04:07:00 +00:00
|
|
|
$input.val("");
|
2013-08-29 10:29:56 +00:00
|
|
|
},
|
|
|
|
update: function () {
|
2013-09-04 04:07:00 +00:00
|
|
|
var data = {
|
2013-09-12 10:34:09 +00:00
|
|
|
title: this.$('input[name=seo_page_title]').val(),
|
|
|
|
description: this.$('input[name=seo_page_title]').val(),
|
2013-09-04 04:07:00 +00:00
|
|
|
keywords: this.keywordList.keywords(),
|
|
|
|
images: this.imageList.images(),
|
|
|
|
};
|
|
|
|
console.log(data);
|
|
|
|
// TODO Persist changes
|
2013-08-29 10:29:56 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
})();
|