SEO code cleanup
bzr revid: ddm@openerp.com-20130904040700-3fctlb1u5k3k1lhy
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
// TODO l10n ?
|
||||
|
||||
var website = openerp.website;
|
||||
website.EditorBar.include({
|
||||
@@ -14,52 +15,33 @@
|
||||
website.seo = {};
|
||||
|
||||
website.seo.PageParser = openerp.Class.extend({
|
||||
init: function () {
|
||||
this._company = $('meta[name="openerp.company"]').attr('value');
|
||||
this._url = this._currentURL();
|
||||
this._title = $(document.title).text();
|
||||
this._headers = {};
|
||||
var _images = [];
|
||||
this._images = _images;
|
||||
|
||||
var self = this;
|
||||
_.each([ 'h1', 'h2', 'h3'], function (header) {
|
||||
self._headers[header] = $(header).map(function () {
|
||||
return $(this).text();
|
||||
}).get();
|
||||
});
|
||||
$('#wrap img').each(function () {
|
||||
var $this = $(this);
|
||||
var img = {
|
||||
src: $this.attr('src'),
|
||||
alt: $this.attr('alt'),
|
||||
};
|
||||
_images.push(img);
|
||||
});
|
||||
},
|
||||
_currentURL: function () {
|
||||
url: function () {
|
||||
var url = window.location.href;
|
||||
var hashIndex = url.indexOf('#');
|
||||
return hashIndex >= 0 ? url.substring(0, hashIndex) : url;
|
||||
},
|
||||
url: function () {
|
||||
return this._url;
|
||||
},
|
||||
title: function () {
|
||||
return this._title;
|
||||
return $(document.title).text();
|
||||
},
|
||||
headers: function () {
|
||||
return this._headers;
|
||||
headers: function (tag) {
|
||||
return $('h1').map(function () {
|
||||
return $(this).text();
|
||||
});
|
||||
},
|
||||
images: function () {
|
||||
return this._images;
|
||||
return $('#wrap img').map(function () {
|
||||
var $img = $(this);
|
||||
return {
|
||||
src: $img.attr('src'),
|
||||
alt: $img.attr('alt'),
|
||||
};
|
||||
});
|
||||
},
|
||||
company: function () {
|
||||
return this._company;
|
||||
return $('meta[name="openerp.company"]').attr('value');
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
website.seo.Tip = openerp.Widget.extend({
|
||||
template: 'website.seo_tip',
|
||||
events: {
|
||||
@@ -67,6 +49,7 @@
|
||||
},
|
||||
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);
|
||||
@@ -78,10 +61,18 @@
|
||||
events: {
|
||||
'click a[data-action=remove-keyword]': 'destroy',
|
||||
},
|
||||
maxWordsPerKeyword: 4, // TODO Check
|
||||
types: {
|
||||
// cf. http://getbootstrap.com/components/#labels
|
||||
// default, primary, success, info, warning, danger
|
||||
perfect: 'success',
|
||||
advised: 'primary',
|
||||
used: 'warning',
|
||||
new: 'default',
|
||||
},
|
||||
init: function (parent, options) {
|
||||
this.keyword = options.keyword;
|
||||
// default, primary, success, info, warning, danger
|
||||
this.type = options.type || 'default';
|
||||
this.type = this.types[options.type || 'default'];
|
||||
this._super(parent);
|
||||
},
|
||||
destroy: function () {
|
||||
@@ -91,18 +82,17 @@
|
||||
});
|
||||
|
||||
website.seo.KeywordList = openerp.Widget.extend({
|
||||
template: 'website.seo_keyword_list',
|
||||
template: 'website.seo_list',
|
||||
maxKeywords: 10,
|
||||
cleanupKeyword: function (word) {
|
||||
return word ? word.replace(/[,;.:<>]+/g, " ").replace(/ +/g, " ").trim() : "";
|
||||
},
|
||||
keywords: function () {
|
||||
return this.$el.find('.js_seo_keyword').map(function () {
|
||||
return $(this).data('keyword');
|
||||
var result = [];
|
||||
this.$el.find('.js_seo_keyword').each(function () {
|
||||
result.push($(this).data('keyword'));
|
||||
});
|
||||
return result;
|
||||
},
|
||||
suggestions: function () {
|
||||
// TODO: Refactor
|
||||
// TODO Refactor (Ugly)
|
||||
return $('.js_seo_suggestion').map(function () {
|
||||
return $(this).data('keyword');
|
||||
});
|
||||
@@ -113,14 +103,12 @@
|
||||
isExistingKeyword: function (word) {
|
||||
return _.contains(this.keywords(), word);
|
||||
},
|
||||
determineType: function (word) {
|
||||
return _.contains(this.suggestions(), word) ? 'success' : 'default';
|
||||
},
|
||||
add: function (word) {
|
||||
add: function (candidate) {
|
||||
var self = this;
|
||||
var word = this.cleanupKeyword(word);
|
||||
// TODO Refine
|
||||
var word = candidate ? candidate.replace(/[,;.:<>]+/g, " ").replace(/ +/g, " ").trim() : "";
|
||||
if (!this.isKeywordListFull() && !this.isExistingKeyword(word)) {
|
||||
var type = this.determineType(word);
|
||||
var type = _.contains(this.suggestions(), word) ? 'advised' : 'new';
|
||||
var keyword = new website.seo.Keyword(this, {
|
||||
keyword: word,
|
||||
type: type,
|
||||
@@ -139,15 +127,21 @@
|
||||
website.seo.Suggestion = openerp.Widget.extend({
|
||||
template: 'website.seo_suggestion',
|
||||
events: {
|
||||
'click .js_seo_suggestion': 'addToSelection'
|
||||
'click .js_seo_suggestion': 'select'
|
||||
},
|
||||
types: {
|
||||
// cf. http://getbootstrap.com/components/#labels
|
||||
// default, primary, success, info, warning, danger
|
||||
primary: 'primary',
|
||||
secondary: 'info',
|
||||
|
||||
},
|
||||
init: function (parent, options) {
|
||||
this.keyword = options.keyword;
|
||||
// default, primary, success, info, warning, danger
|
||||
this.type = options.type || 'default';
|
||||
this.type = this.types[options.type || 'primary'];
|
||||
this._super(parent);
|
||||
},
|
||||
addToSelection: function () {
|
||||
select: function () {
|
||||
this.trigger('selected');
|
||||
},
|
||||
});
|
||||
@@ -158,7 +152,31 @@
|
||||
this.src = options.src;
|
||||
this.alt = options.alt;
|
||||
this._super(parent);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
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 = [];
|
||||
this.$el.find('input').each(function () {
|
||||
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);
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Configurator = openerp.Widget.extend({
|
||||
@@ -166,25 +184,22 @@
|
||||
events: {
|
||||
'keypress input[name=seo_page_keywords]': 'confirmKeyword',
|
||||
'click button[data-action=add]': 'addKeyword',
|
||||
'click a[data-action=update]': 'update',
|
||||
'click button[data-action=update]': 'update',
|
||||
'hidden.bs.modal': 'destroy'
|
||||
},
|
||||
|
||||
maxTitleSize: 65,
|
||||
maxDescriptionSize: 155,
|
||||
maxWordsPerKeyword: 4,
|
||||
|
||||
start: function () {
|
||||
var pageParser = new website.seo.PageParser();
|
||||
this.$el.find('.js_seo_page_url').text(pageParser.url());
|
||||
this.$el.find('input[name=seo_page_title]').val(pageParser.title());
|
||||
this.checkBestPractices(pageParser);
|
||||
this.displayKeywordSuggestions(pageParser);
|
||||
this.displayImages(pageParser);
|
||||
this.keywordList = new website.seo.KeywordList(this);
|
||||
this.keywordList.appendTo(this.$el.find('.js_seo_keywords_list'));
|
||||
|
||||
var $modal = this.$el;
|
||||
var pageParser = new website.seo.PageParser();
|
||||
$modal.find('.js_seo_page_url').text(pageParser.url());
|
||||
$modal.find('input[name=seo_page_title]').val(pageParser.title());
|
||||
this.suggestImprovements(pageParser);
|
||||
this.displayKeywordSuggestions(pageParser);
|
||||
this.imageList = new website.seo.ImageList(this);
|
||||
this.imageList.appendTo($modal.find('.js_seo_image_list'));
|
||||
this.keywordList = new website.seo.KeywordList(this);
|
||||
this.keywordList.appendTo($modal.find('.js_seo_keywords_list'));
|
||||
this.keywordList.on('list-full', null, function () {
|
||||
$modal.find('input[name=seo_page_keywords]')
|
||||
.attr('readonly', "readonly")
|
||||
@@ -198,9 +213,9 @@
|
||||
$modal.find('button[data-action=add]')
|
||||
.prop('disabled', false).removeClass('disabled');
|
||||
});
|
||||
this.$el.modal();
|
||||
$modal.modal();
|
||||
},
|
||||
checkBestPractices: function (parser) {
|
||||
suggestImprovements: function (parser) {
|
||||
var tips = [];
|
||||
var self = this;
|
||||
function displayTip(message, type) {
|
||||
@@ -210,19 +225,18 @@
|
||||
}).appendTo(self.$el.find('.js_seo_tips'));
|
||||
}
|
||||
var pageParser = parser || new website.seo.PageParser();
|
||||
if (pageParser.headers()['h1'].length === 0) {
|
||||
if (!pageParser.headers('h1').length === 0) {
|
||||
tips.push({
|
||||
type: 'warning',
|
||||
message: "You don't have an <h1> tag on your page."
|
||||
message: "You don't have an <h1> tag on your page.",
|
||||
});
|
||||
}
|
||||
if (pageParser.headers()['h1'].length > 1) {
|
||||
if (pageParser.headers('h1').length > 1) {
|
||||
tips.push({
|
||||
type: 'warning',
|
||||
message: "You have more than one <h1> tag on your page."
|
||||
message: "You have more than one <h1> tag on your page.",
|
||||
});
|
||||
}
|
||||
|
||||
if (tips.length > 0) {
|
||||
_.each(tips, function (tip) {
|
||||
displayTip(tip.message, tip.type);
|
||||
@@ -233,16 +247,19 @@
|
||||
},
|
||||
displayKeywordSuggestions: function (pageParser) {
|
||||
var $modal = this.$el;
|
||||
var companyName = pageParser.company().toLowerCase();
|
||||
var requestURL = "http://seo.eu01.aws.af.cm/suggest/" + encodeURIComponent(companyName);
|
||||
$modal.find('.js_seo_company_suggestions').append("Loading...");
|
||||
var self = this;
|
||||
var companyName = pageParser.company().toLowerCase();
|
||||
|
||||
$modal.find('.js_seo_company_suggestions').append("Loading...");
|
||||
// TODO Improve algorithm + Ajust based on custom user keywords
|
||||
var requestURL = "http://seo.eu01.aws.af.cm/suggest/" + encodeURIComponent(companyName);
|
||||
$.getJSON(requestURL, function (list) {
|
||||
$modal.find('.js_seo_company_suggestions').empty();
|
||||
var nameRegex = new RegExp(companyName, "gi");
|
||||
var cleanList = _.map(list, function (word) {
|
||||
var cleanList = _.map(list, function removeCompanyName (word) {
|
||||
return word.replace(nameRegex, "").trim();
|
||||
});
|
||||
// TODO Order properly ?
|
||||
cleanList.push(companyName);
|
||||
_.each(_.uniq(cleanList), function (keyword) {
|
||||
if (keyword) {
|
||||
@@ -257,32 +274,26 @@
|
||||
});
|
||||
});
|
||||
},
|
||||
displayImages: function (pageParser) {
|
||||
var $container = this.$el.find('.js_seo_images');
|
||||
$container.empty();
|
||||
var self = this;
|
||||
_.each(pageParser.images(), function (image) {
|
||||
new website.seo.Image(self, image).appendTo($container);
|
||||
});
|
||||
},
|
||||
currentPage: function () {
|
||||
var url = window.location.href;
|
||||
var hashIndex = url.indexOf('#');
|
||||
return hashIndex > 0 ? url.substring(0, hashIndex): url;
|
||||
},
|
||||
confirmKeyword: function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
this.addKeyword();
|
||||
this.addKeyword(this.$el.find('input[name=seo_page_keywords]').val());
|
||||
}
|
||||
},
|
||||
addKeyword: function (keyword) {
|
||||
var $modal = this.$el;
|
||||
var candidate = keyword || $modal.find('input[name=seo_page_keywords]').val();
|
||||
this.keywordList.add(candidate);
|
||||
$modal.find('input[name=seo_page_keywords]').val("");
|
||||
addKeyword: function (word) {
|
||||
var $input = this.$el.find('input[name=seo_page_keywords]');
|
||||
var keyword = _.isString(word) ? word : $input.val();
|
||||
this.keywordList.add(keyword);
|
||||
$input.val("");
|
||||
},
|
||||
update: function () {
|
||||
// TODO: Persist changes
|
||||
var data = {
|
||||
title: this.$el.find('input[name=seo_page_title]').val(),
|
||||
description: this.$el.find('input[name=seo_page_title]').val(),
|
||||
keywords: this.keywordList.keywords(),
|
||||
images: this.imageList.images(),
|
||||
};
|
||||
console.log(data);
|
||||
// TODO Persist changes
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="page-header">3. Describe your images</h3>
|
||||
<div class="row js_seo_images">
|
||||
<div class="row js_seo_image_list">
|
||||
<!-- filled in JS -->
|
||||
</div>
|
||||
</section>
|
||||
@@ -131,6 +131,12 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.seo_list">
|
||||
<ul class="list-inline">
|
||||
<!-- filled in JS -->
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
<t t-name="website.seo_tip">
|
||||
<div t-attf-class="alert alert-#{widget.type}">
|
||||
<button title="Dismiss" type="button" class="close" data-action="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
@@ -148,12 +154,6 @@
|
||||
</li>
|
||||
</t>
|
||||
|
||||
<t t-name="website.seo_keyword_list">
|
||||
<ul class="list-inline">
|
||||
<!-- filled in JS -->
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
<t t-name="website.seo_suggestion">
|
||||
<li class="oe_seo_suggestion">
|
||||
<span t-attf-class="label label-#{ widget.type } js_seo_suggestion" t-att-data-keyword="widget.keyword">
|
||||
@@ -165,7 +165,7 @@
|
||||
<t t-name="website.seo_image">
|
||||
<div class="col-sm-6 col-md-3 oe_seo_image_preview">
|
||||
<img t-att-src="widget.src" class="img-rounded thumbnail"/>
|
||||
<input type="text" class="form-control" t-att-value="widget.alt" placeholder="Description..."/>
|
||||
<input type="text" class="form-control" t-att-src="widget.src" t-att-value="widget.alt" placeholder="Description..."/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user