[extensions-web] comments: implemented proper preview.



commit 989c251a530261fe624dc545c4d7c6a9527cb6fc
Author: Yuri Konotopov <ykonotopov gnome org>
Date:   Sun Jan 29 15:41:01 2017 +0400

    comments: implemented proper preview.
    
    Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=766476

 sweettooth/extensions/views.py                     |    3 +-
 sweettooth/ratings/templates/comments/form.html    |    6 +-
 sweettooth/ratings/templates/comments/preview.html |   56 +
 sweettooth/static/js/jquery.raty.js                | 1231 ++++++++++++--------
 sweettooth/static/js/main.js                       |   30 +-
 5 files changed, 848 insertions(+), 478 deletions(-)
---
diff --git a/sweettooth/extensions/views.py b/sweettooth/extensions/views.py
index c9b3691..5bd9a1a 100644
--- a/sweettooth/extensions/views.py
+++ b/sweettooth/extensions/views.py
@@ -246,7 +246,8 @@ def extension_view(request, obj, **kwargs):
     context = dict(shell_version_map = json.dumps(extension.visible_shell_version_map),
                    extension = extension,
                    all_versions = extension.versions.order_by('-version'),
-                   is_visible = extension.latest_version is not None)
+                   is_visible = extension.latest_version is not None,
+                   next=extension.get_absolute_url())
     return render(request, template_name, context)
 
 @require_POST
diff --git a/sweettooth/ratings/templates/comments/form.html b/sweettooth/ratings/templates/comments/form.html
index 98b9542..c8e1322 100644
--- a/sweettooth/ratings/templates/comments/form.html
+++ b/sweettooth/ratings/templates/comments/form.html
@@ -17,5 +17,9 @@
     {% endifnotequal %}
   {% endfor %}
   <div class="rating"></div>
-  <input type="submit" name="post" value="{% trans "Post" %}" />
+  <input type="hidden" name="show_rating" value="1" />
+  <p class="submit">
+    <input type="submit" name="post" class="submit-post" value="{% trans "Post" %}"/>
+    <input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}"/>
+  </p>
 </form>
diff --git a/sweettooth/ratings/templates/comments/preview.html 
b/sweettooth/ratings/templates/comments/preview.html
new file mode 100644
index 0000000..9002af4
--- /dev/null
+++ b/sweettooth/ratings/templates/comments/preview.html
@@ -0,0 +1,56 @@
+{% extends "base.html" %}
+{% load comments i18n %}
+
+{% block title %}{% trans "Preview your comment" %}{% endblock %}
+
+{% block body %}
+    {% if request.user.is_authenticated %}
+    <div id="rating_form" class="preview">
+        <form action="{% comment_form_target %}" method="post">{% csrf_token %}
+            {% if next %}
+                <div><input type="hidden" name="next" value="{{ next }}"/></div>{% endif %}
+            {% if form.errors %}
+                <h1>{% blocktrans count counter=form.errors|length %}Please correct the error below{% plural 
%}Please
+                    correct the errors below{% endblocktrans %}</h1>
+            {% else %}
+                <h1>{% trans "Preview your comment" %}</h1>
+                <blockquote>{{ comment|linebreaks }}</blockquote>
+                <p>
+                    {% trans "and" %} <input type="submit" name="submit" class="submit-post"
+                                             value="{% trans "Post your comment" %}"
+                                             id="submit"/> {% trans "or make changes" %}:
+                </p>
+            {% endif %}
+            {% for field in form %}
+                {% ifnotequal field.name "rating" %}
+                    {% if field.is_hidden %}
+                        <div>{{ field }}</div>
+                    {% else %}
+                        {% if field.errors %}{{ field.errors }}{% endif %}
+                        <p
+                                {% if field.errors %} class="error"{% endif %}
+                                {% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}>
+                            {% ifnotequal field.name "comment" %}{{ field.label_tag }} {% endifnotequal %}{{ 
field }}
+                        </p>
+                    {% endif %}
+                {% else %}
+                    <input type="hidden" name="rating_initial" value="{{ field.value }}" />
+                {% endifnotequal %}
+            {% endfor %}
+            <div class="rating"></div>
+            <input type="hidden" name="show_rating" value="{{ form.data.show_rating }}" />
+            <p class="submit">
+                <input type="submit" name="submit" class="submit-post" value="{% trans "Post" %}"/>
+                <input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}"/>
+            </p>
+        </form>
+    </div>
+    {% else %}
+        <p class="unauthenticated">
+            Unfortunately, to help prevent spam, we require that you <a href="{% url 'auth-login' %}">log in 
to GNOME
+            Shell Extensions</a> in order to post a comment or report an error. You understand, right?
+        </p>
+    {% endif %}
+{% endblock %}
+
+{% block navclass %}main{% endblock %}
diff --git a/sweettooth/static/js/jquery.raty.js b/sweettooth/static/js/jquery.raty.js
index c6b4255..4ed9443 100644
--- a/sweettooth/static/js/jquery.raty.js
+++ b/sweettooth/static/js/jquery.raty.js
@@ -1,471 +1,760 @@
-/*!
- * jQuery Raty - A Star Rating Plugin - http://wbotelhos.com/raty
- * ---------------------------------------------------------------------
- *
- * jQuery Raty is a plugin that generates a customizable star rating.
- *
- * Licensed under The MIT License
- *
- * @version        2.1.0
- * @since          2010.06.11
- * @author         Washington Botelho
- * @documentation  wbotelhos.com/raty
- * @twitter        twitter.com/wbotelhos
- *
- * Usage with default values:
- * ---------------------------------------------------------------------
- * $('#star').raty();
- *
- * <div id="star"></div>
- *
- * $('.star').raty();
- *
- * <div class="star"></div>
- * <div class="star"></div>
- * <div class="star"></div>
- *
- */
-
-;(function($) {
-
-       var methods = {
-               init: function(options) {
-                       return this.each(function() {
-
-                               var opt         = $.extend({}, $.fn.raty.defaults, options),
-                                       $this   = $(this).data('options', opt);
-
-                               if (opt.number > 20) {
-                                       opt.number = 20;
-                               } else if (opt.number < 0) {
-                                       opt.number = 0;
-                               }
-
-                               if (opt.round.down === undefined) {
-                                       opt.round.down = $.fn.raty.defaults.round.down;
-                               }
-
-                               if (opt.round.full === undefined) {
-                                       opt.round.full = $.fn.raty.defaults.round.full;
-                               }
-
-                               if (opt.round.up === undefined) {
-                                       opt.round.up = $.fn.raty.defaults.round.up;
-                               }
-
-                               if (opt.path.substring(opt.path.length - 1, opt.path.length) != '/') {
-                                       opt.path += '/';
-                               }
-
-                               if (typeof opt.start == 'function') {
-                                       opt.start = opt.start.call(this);
-                               }
-
-                               var isValidStart        = !isNaN(parseInt(opt.start, 10)),
-                                       start                   = '';
-
-                               if (isValidStart) {
-                                       start = (opt.start > opt.number) ? opt.number : opt.start;
-                               } 
-
-                               var starFile    = opt.starOn,
-                                       space           = (opt.space) ? 4 : 0,
-                                       hint            = '';
-
-                               for (var i = 1; i <= opt.number; i++) {
-                                       starFile = (start < i) ? opt.starOff : opt.starOn;
-
-                                       hint = (i <= opt.hintList.length && opt.hintList[i - 1] !== null) ? 
opt.hintList[i - 1] : i;
-
-                                       $this.append('<img src="' + opt.path + starFile + '" alt="' + i + '" 
title="' + hint + '" />');
-
-                                       if (opt.space) {
-                                               $this.append((i < opt.number) ? '&nbsp;' : '');
-                                       }
-                               }
-
-                               var $score = $('<input/>', { type: 'hidden', name: 
opt.scoreName}).appendTo($this);
-
-                               if (isValidStart) {
-                                       if (opt.start > 0) {
-                                               $score.val(start);
-                                       }
-
-                                       methods.roundStar.call($this, start);
-                               }
-
-                               if (opt.iconRange) {
-                                       methods.fillStar.call($this, start);    
-                               }
-
-                               methods.setTarget.call($this, start, opt.targetKeep);
-
-                               var width = opt.width || (opt.number * opt.size + opt.number * space);
-
-                               if (opt.cancel) {
-                                       var $cancel = $('<img src="' + opt.path + opt.cancelOff + '" alt="x" 
title="' + opt.cancelHint + '" class="raty-cancel"/>');
-
-                                       if (opt.cancelPlace == 'left') {
-                                               $this.prepend('&nbsp;').prepend($cancel);
-                                       } else {
-                                               $this.append('&nbsp;').append($cancel);
-                                       }
-
-                                       width += opt.size + space;
-                               }
-
-                               if (opt.readOnly) {
-                                       methods.fixHint.call($this);
-
-                                       $this.children('.raty-cancel').hide();
-                               } else {
-                                       $this.css('cursor', 'pointer');
-
-                                       methods.bindAction.call($this);
-                               }
-
-                               $this.css('width', width);
-                       });
-               }, bindAction: function() {
-                       var self        = this,
-                               opt             = this.data('options'),
-                               $score  = this.children('input');
-
-                       self.mouseleave(function() {
-                               methods.initialize.call(self, $score.val());
-
-                               methods.setTarget.call(self, $score.val(), opt.targetKeep);
-                       });
-
-                       var $stars      = this.children('img').not('.raty-cancel'),
-                               action  = (opt.half) ? 'mousemove' : 'mouseover';
-
-                       if (opt.cancel) {
-                               self.children('.raty-cancel').mouseenter(function() {
-                                       $(this).attr('src', opt.path + opt.cancelOn);
-
-                                       $stars.attr('src', opt.path + opt.starOff);
-
-                                       methods.setTarget.call(self, null, true);
-                               }).mouseleave(function() {
-                                       $(this).attr('src', opt.path + opt.cancelOff);
-
-                                       self.mouseout();
-                               }).click(function(evt) {
-                                       $score.removeAttr('value');
-
-                                       if (opt.click) {
-                                 opt.click.call(self[0], null, evt);
-                               }
-                               });
-                       }
-
-                       $stars.bind(action, function(evt) {
-                               var value = parseInt(this.alt, 10);
-
-                               if (opt.half) {
-                                       var position    = parseFloat((evt.pageX - $(this).offset().left) / 
opt.size),
-                                               diff            = (position > .5) ? 1 : .5;
-
-                                       value = parseFloat(this.alt) - 1 + diff;
-
-                                       methods.fillStar.call(self, value);
-
-                                       if (opt.precision) {
-                                               value = value - diff + position;
-                                       }
-
-                                       methods.showHalf.call(self, value);
-                               } else {
-                                       methods.fillStar.call(self, value);
-                               }
-
-                               self.data('score', value);
-
-                               methods.setTarget.call(self, value, true);
-                       }).click(function(evt) {
-                               $score.val((opt.half || opt.precision) ? self.data('score') : this.alt);
-
-                               if (opt.click) {
-                                       opt.click.call(self[0], $score.val(), evt);
-                               }
-                       });
-               }, cancel: function(isClick) {
-                       return this.each(function() {
-                               var $this = $(this);
-
-                               if ($this.data('readonly') == 'readonly') {
-                                       return false;
-                               }
-
-                               if (isClick) {
-                                       methods.click.call($this, null);
-                               } else {
-                                       methods.start.call($this, null);
-                               }
-
-                               $this.mouseleave().children('input').removeAttr('value');
-                       });
-               }, click: function(score) {
-                       return this.each(function() {
-                               var $this = $(this);
-
-                               if ($this.data('readonly') == 'readonly') {
-                                       return false;
-                               }
-
-                               methods.initialize.call($this, score);
-
-                               var opt = $this.data('options');
-
-                               if (opt.click) {
-                                       opt.click.call($this[0], score);
-                               } else {
-                                       $.error('you must add the "click: function(score, evt) { }" 
callback.');
-                               }
-
-                               methods.setTarget.call($this, score, true);
-                       });
-               }, fillStar: function(score) {
-                       var opt         = this.data('options'),
-                               $stars  = this.children('img').not('.raty-cancel'),
-                               qtyStar = $stars.length,
-                               count   = 0,
-                               $star   ,
-                               star    ,
-                               icon    ;
-
-                       for (var i = 1; i <= qtyStar; i++) {
-                               $star = $stars.eq(i - 1);
-
-                               if (opt.iconRange && opt.iconRange.length > count) {
-                                       star = opt.iconRange[count];
-
-                                       if (opt.single) {
-                                               icon = (i == score) ? (star.on || opt.starOn) : (star.off || 
opt.starOff);
-                                       } else {
-                                               icon = (i <= score) ? (star.on || opt.starOn) : (star.off || 
opt.starOff);
-                                       }
-
-                                       if (i <= star.range) {
-                                               $star.attr('src', opt.path + icon);
-                                       }
-
-                                       if (i == star.range) {
-                                               count++;
-                                       }
-                               } else {
-                                       if (opt.single) {
-                                               icon = (i == score) ? opt.starOn : opt.starOff;
-                                       } else {
-                                               icon = (i <= score) ? opt.starOn : opt.starOff;
-                                       }
-
-                                       $star.attr('src', opt.path + icon);
-                               }
-                       }
-               }, fixHint: function() {
-                       var opt         = this.data('options'),
-                               $score  = this.children('input'),
-                               score   = parseInt($score.val(), 10),
-                               hint    = opt.noRatedMsg;
-
-                       if (!isNaN(score) && score > 0) {
-                               hint = (score <= opt.hintList.length && opt.hintList[score - 1] !== null) ? 
opt.hintList[score - 1] : score;
-                       }
-
-                       $score.attr('readonly', 'readonly');
-                       this.css('cursor', 'default').data('readonly', 'readonly').attr('title', 
hint).children('img').attr('title', hint);
-               }, readOnly: function(isReadOnly) {
-                       return this.each(function() {
-                               var $this       = $(this),
-                                       $cancel = $this.children('.raty-cancel');
-
-                               if ($cancel.length) {
-                                       if (isReadOnly) {
-                                               $cancel.hide();
-                                       } else {
-                                               $cancel.show();
-                                       }
-                               }
-
-                               if (isReadOnly) {
-                                       $this.unbind();
-
-                                       $this.children('img').unbind();
-
-                                       methods.fixHint.call($this);
-                               } else {
-                                       methods.bindAction.call($this);
-
-                                       methods.unfixHint.call($this);
-                               }
-                       });
-               }, roundStar: function(score) {
-                       var opt         = this.data('options'),
-                               diff    = (score - Math.floor(score)).toFixed(2);
-
-                       if (diff > opt.round.down) {
-                               var icon = opt.starOn;                                          // Full up: 
[x.76 .. x.99]
-
-                               if (diff < opt.round.up && opt.halfShow) {      // Half: [x.26 .. x.75]
-                                       icon = opt.starHalf;
-                               } else if (diff < opt.round.full) {                     // Full down: [x.00 
.. x.5]
-                                       icon = opt.starOff;
-                               }
-
-                               this.children('img').not('.raty-cancel').eq(Math.ceil(score) - 1).attr('src', 
opt.path + icon);
-                       }                                                                                     
          // Full down: [x.00 .. x.25]
-               }, score: function() {
-                       var score       = [],
-                               value   ;
-
-                       this.each(function() {
-                               value = $(this).children('input').val();
-                               value = (value == '') ? null : parseFloat(value);
-
-                               score.push(value);
-                       });
-
-                       return (score.length > 1) ? score : score[0];
-               }, setTarget: function(value, isKeep) {
-                       var opt = this.data('options');
-
-                       if (opt.target) {
-                               var $target = $(opt.target);
-
-                               if ($target.length == 0) {
-                                       $.error('target selector invalid or missing!');
-                               } else {
-                                       var score = value;
-
-                                       if (score == null && !opt.cancel) {
-                                               $.error('you must enable the "cancel" option to set hint on 
target.');
-                                       } else {
-                                               if (!isKeep || score == '') {
-                                                       score = opt.targetText;
-                                               } else {
-                                                       if (opt.targetType == 'hint') {
-                                                               if (score === null && opt.cancel) {
-                                                                       score = opt.cancelHint;
-                                                               } else {
-                                                                       score = opt.hintList[Math.ceil(score 
- 1)];
-                                                               }
-                                                       } else {
-                                                               if (score != '' && !opt.precision) {
-                                                                       score = parseInt(score, 10);
-                                                               } else {
-                                                                       score = parseFloat(score).toFixed(1);
-                                                               }
-                                                       }
-                                               }
-
-                                               if (opt.targetFormat.indexOf('{score}') < 0) {
-                                                       $.error('template "{score}" missing!');
-                                               } else if (value !== null) {
-                                                       score = 
opt.targetFormat.toString().replace('{score}', score);
-                                               }
-
-                                               if ($target.is(':input')) {
-                                                       $target.val(score);
-                                               } else {
-                                                       $target.html(score);
-                                               }
-                                       }
-                               }
-                       }
-               }, showHalf: function(score) {
-                       var opt         = this.data('options'),
-                               diff    = (score - Math.floor(score)).toFixed(1);
-
-                       if (diff > 0 && diff < .6) {
-                               this.children('img').not('.raty-cancel').eq(Math.ceil(score) - 1).attr('src', 
opt.path + opt.starHalf);
-                       }
-               }, start: function(score) {
-                       return this.each(function() {
-                               var $this = $(this);
-
-                               if ($this.data('readonly') == 'readonly') {
-                                       return false;
-                               }
-
-                               methods.initialize.call($this, score);
-
-                               var opt = $this.data('options');
-
-                               methods.setTarget.call($this, score, true);
-                       });
-               }, initialize: function(score) {
-                       var opt = this.data('options');
-
-                       if (score < 0) {
-                               score = 0;
-                       } else if (score > opt.number) {
-                               score = opt.number;
-                       }
-
-                       methods.fillStar.call(this, score);
-
-                       if (score != '') {
-                               if (opt.halfShow) {
-                                       methods.roundStar.call(this, score);
-                               }
-
-                               this.children('input').val(score);
-                       }
-               }, unfixHint: function() {
-                       var opt         = this.data('options'),
-                               $imgs   = this.children('img').filter(':not(.raty-cancel)');
-
-                       for (var i = 0; i < opt.number; i++) {
-                               $imgs.eq(i).attr('title', (i < opt.hintList.length && opt.hintList[i] !== 
null) ? opt.hintList[i] : i);
-                       }
-
-                       this.css('cursor', 
'pointer').removeData('readonly').removeAttr('title').children('input').attr('readonly', 'readonly');
-               }
-       };
-
-       $.fn.raty = function(method) {
-               if (methods[method]) {
-                       return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
-               } else if (typeof method === 'object' || !method) {
-                       return methods.init.apply(this, arguments);
-               } else {
-                       $.error('Method ' + method + ' does not exist!');
-               } 
-       };
-
-       $.fn.raty.defaults = {
-               cancel:                 false,
-               cancelHint:             'cancel this rating!',
-               cancelOff:              'cancel-off.png',
-               cancelOn:               'cancel-on.png',
-               cancelPlace:    'left',
-               click:                  undefined,
-               half:                   false,
-               halfShow:               true,
-               hintList:               ['bad', 'poor', 'regular', 'good', 'gorgeous'],
-               iconRange:              undefined,
-               noRatedMsg:             'not rated yet',
-               number:                 5,
-               path:                   'img/',
-               precision:              false,
-               round:                  { down: .25, full: .6, up: .76 },
-               readOnly:               false,
-               scoreName:              'score',
-               single:                 false,
-               size:                   16,
-               space:                  true,
-               starHalf:               'star-half.png',
-               starOff:                'star-off.png',
-               starOn:                 'star-on.png',
-               start:                  0,
-               target:                 undefined,
-               targetFormat:   '{score}',
-               targetKeep:             false,
-               targetText:             '',
-               targetType:             'hint',
-               width:                  undefined
-       };
-
-})(jQuery);
+/*!
+ * jQuery Raty - A Star Rating Plugin
+ *
+ * The MIT License
+ *
+ * @author  : Washington Botelho
+ * @doc     : http://wbotelhos.com/raty
+ * @version : 2.7.1
+ *
+ */
+
+;
+(function($) {
+  'use strict';
+
+  var methods = {
+    init: function(options) {
+      return this.each(function() {
+        this.self = $(this);
+
+        methods.destroy.call(this.self);
+
+        this.opt = $.extend(true, {}, $.fn.raty.defaults, options);
+
+        methods._adjustCallback.call(this);
+        methods._adjustNumber.call(this);
+        methods._adjustHints.call(this);
+
+        this.opt.score = methods._adjustedScore.call(this, this.opt.score);
+
+        if (this.opt.starType !== 'img') {
+          methods._adjustStarType.call(this);
+        }
+
+        methods._adjustPath.call(this);
+        methods._createStars.call(this);
+
+        if (this.opt.cancel) {
+          methods._createCancel.call(this);
+        }
+
+        if (this.opt.precision) {
+          methods._adjustPrecision.call(this);
+        }
+
+        methods._createScore.call(this);
+        methods._apply.call(this, this.opt.score);
+        methods._setTitle.call(this, this.opt.score);
+        methods._target.call(this, this.opt.score);
+
+        if (this.opt.readOnly) {
+          methods._lock.call(this);
+        } else {
+          this.style.cursor = 'pointer';
+
+          methods._binds.call(this);
+        }
+      });
+    },
+
+    _adjustCallback: function() {
+      var options = ['number', 'readOnly', 'score', 'scoreName', 'target', 'path'];
+
+      for (var i = 0; i < options.length; i++) {
+        if (typeof this.opt[options[i]] === 'function') {
+          this.opt[options[i]] = this.opt[options[i]].call(this);
+        }
+      }
+    },
+
+    _adjustedScore: function(score) {
+      if (!score) {
+        return score;
+      }
+
+      return methods._between(score, 0, this.opt.number);
+    },
+
+    _adjustHints: function() {
+      if (!this.opt.hints) {
+        this.opt.hints = [];
+      }
+
+      if (!this.opt.halfShow && !this.opt.half) {
+        return;
+      }
+
+      var steps = this.opt.precision ? 10 : 2;
+
+      for (var i = 0; i < this.opt.number; i++) {
+        var group = this.opt.hints[i];
+
+        if (Object.prototype.toString.call(group) !== '[object Array]') {
+          group = [group];
+        }
+
+        this.opt.hints[i] = [];
+
+        for (var j = 0; j < steps; j++) {
+          var
+            hint = group[j],
+            last = group[group.length - 1];
+
+          if (last === undefined) {
+            last = null;
+          }
+
+          this.opt.hints[i][j] = hint === undefined ? last : hint;
+        }
+      }
+    },
+
+    _adjustNumber: function() {
+      this.opt.number = methods._between(this.opt.number, 1, this.opt.numberMax);
+    },
+
+    _adjustPath: function() {
+      this.opt.path = this.opt.path || '';
+
+      if (this.opt.path && this.opt.path.charAt(this.opt.path.length - 1) !== '/') {
+        this.opt.path += '/';
+      }
+    },
+
+    _adjustPrecision: function() {
+      this.opt.half = true;
+    },
+
+    _adjustStarType: function() {
+      var replaces = ['cancelOff', 'cancelOn', 'starHalf', 'starOff', 'starOn'];
+
+      this.opt.path = '';
+
+      for (var i = 0; i < replaces.length; i++) {
+        this.opt[replaces[i]] = this.opt[replaces[i]].replace('.', '-');
+      }
+    },
+
+    _apply: function(score) {
+      methods._fill.call(this, score);
+
+      if (score) {
+        if (score > 0) {
+          this.score.val(score);
+        }
+
+        methods._roundStars.call(this, score);
+      }
+    },
+
+    _between: function(value, min, max) {
+      return Math.min(Math.max(parseFloat(value), min), max);
+    },
+
+    _binds: function() {
+      if (this.cancel) {
+        methods._bindOverCancel.call(this);
+        methods._bindClickCancel.call(this);
+        methods._bindOutCancel.call(this);
+      }
+
+      methods._bindOver.call(this);
+      methods._bindClick.call(this);
+      methods._bindOut.call(this);
+    },
+
+    _bindClick: function() {
+      var that = this;
+
+      that.stars.on('click.raty', function(evt) {
+        var
+          execute = true,
+          score   = (that.opt.half || that.opt.precision) ? that.self.data('score') : (this.alt || 
$(this).data('alt'));
+
+        if (that.opt.click) {
+          execute = that.opt.click.call(that, +score, evt);
+        }
+
+        if (execute || execute === undefined) {
+          if (that.opt.half && !that.opt.precision) {
+            score = methods._roundHalfScore.call(that, score);
+          }
+
+          methods._apply.call(that, score);
+        }
+      });
+    },
+
+    _bindClickCancel: function() {
+      var that = this;
+
+      that.cancel.on('click.raty', function(evt) {
+        that.score.removeAttr('value');
+
+        if (that.opt.click) {
+          that.opt.click.call(that, null, evt);
+        }
+      });
+    },
+
+    _bindOut: function() {
+      var that = this;
+
+      that.self.on('mouseleave.raty', function(evt) {
+        var score = +that.score.val() || undefined;
+
+        methods._apply.call(that, score);
+        methods._target.call(that, score, evt);
+        methods._resetTitle.call(that);
+
+        if (that.opt.mouseout) {
+          that.opt.mouseout.call(that, score, evt);
+        }
+      });
+    },
+
+    _bindOutCancel: function() {
+      var that = this;
+
+      that.cancel.on('mouseleave.raty', function(evt) {
+        var icon = that.opt.cancelOff;
+
+        if (that.opt.starType !== 'img') {
+          icon = that.opt.cancelClass + ' ' + icon;
+        }
+
+        methods._setIcon.call(that, this, icon);
+
+        if (that.opt.mouseout) {
+          var score = +that.score.val() || undefined;
+
+          that.opt.mouseout.call(that, score, evt);
+        }
+      });
+    },
+
+    _bindOver: function() {
+      var that   = this,
+          action = that.opt.half ? 'mousemove.raty' : 'mouseover.raty';
+
+      that.stars.on(action, function(evt) {
+        var score = methods._getScoreByPosition.call(that, evt, this);
+
+        methods._fill.call(that, score);
+
+        if (that.opt.half) {
+          methods._roundStars.call(that, score, evt);
+          methods._setTitle.call(that, score, evt);
+
+          that.self.data('score', score);
+        }
+
+        methods._target.call(that, score, evt);
+
+        if (that.opt.mouseover) {
+          that.opt.mouseover.call(that, score, evt);
+        }
+      });
+    },
+
+    _bindOverCancel: function() {
+      var that = this;
+
+      that.cancel.on('mouseover.raty', function(evt) {
+        var
+          starOff = that.opt.path + that.opt.starOff,
+          icon    = that.opt.cancelOn;
+
+        if (that.opt.starType === 'img') {
+          that.stars.attr('src', starOff);
+        } else {
+          icon = that.opt.cancelClass + ' ' + icon;
+
+          that.stars.attr('class', starOff);
+        }
+
+        methods._setIcon.call(that, this, icon);
+        methods._target.call(that, null, evt);
+
+        if (that.opt.mouseover) {
+          that.opt.mouseover.call(that, null);
+        }
+      });
+    },
+
+    _buildScoreField: function() {
+      return $('<input />', { name: this.opt.scoreName, type: 'hidden' }).appendTo(this);
+    },
+
+    _createCancel: function() {
+      var icon   = this.opt.path + this.opt.cancelOff,
+          cancel = $('<' + this.opt.starType + ' />', { title: this.opt.cancelHint, 'class': 
this.opt.cancelClass });
+
+      if (this.opt.starType === 'img') {
+        cancel.attr({ src: icon, alt: 'x' });
+      } else {
+        // TODO: use $.data
+        cancel.attr('data-alt', 'x').addClass(icon);
+      }
+
+      if (this.opt.cancelPlace === 'left') {
+        this.self.prepend('&#160;').prepend(cancel);
+      } else {
+        this.self.append('&#160;').append(cancel);
+      }
+
+      this.cancel = cancel;
+    },
+
+    _createScore: function() {
+      var score = $(this.opt.targetScore);
+
+      this.score = score.length ? score : methods._buildScoreField.call(this);
+    },
+
+    _createStars: function() {
+      for (var i = 1; i <= this.opt.number; i++) {
+        var
+          name  = methods._nameForIndex.call(this, i),
+          attrs = { alt: i, src: this.opt.path + this.opt[name] };
+
+        if (this.opt.starType !== 'img') {
+          attrs = { 'data-alt': i, 'class': attrs.src }; // TODO: use $.data.
+        }
+
+        attrs.title = methods._getHint.call(this, i);
+
+        $('<' + this.opt.starType + ' />', attrs).appendTo(this);
+
+        if (this.opt.space) {
+          this.self.append(i < this.opt.number ? '&#160;' : '');
+        }
+      }
+
+      this.stars = this.self.children(this.opt.starType);
+    },
+
+    _error: function(message) {
+      $(this).text(message);
+
+      $.error(message);
+    },
+
+    _fill: function(score) {
+      var hash = 0;
+
+      for (var i = 1; i <= this.stars.length; i++) {
+        var
+          icon,
+          star   = this.stars[i - 1],
+          turnOn = methods._turnOn.call(this, i, score);
+
+        if (this.opt.iconRange && this.opt.iconRange.length > hash) {
+          var irange = this.opt.iconRange[hash];
+
+          icon = methods._getRangeIcon.call(this, irange, turnOn);
+
+          if (i <= irange.range) {
+            methods._setIcon.call(this, star, icon);
+          }
+
+          if (i === irange.range) {
+            hash++;
+          }
+        } else {
+          icon = this.opt[turnOn ? 'starOn' : 'starOff'];
+
+          methods._setIcon.call(this, star, icon);
+        }
+      }
+    },
+
+    _getFirstDecimal: function(number) {
+      var
+        decimal = number.toString().split('.')[1],
+        result  = 0;
+
+      if (decimal) {
+        result = parseInt(decimal.charAt(0), 10);
+
+        if (decimal.slice(1, 5) === '9999') {
+          result++;
+        }
+      }
+
+      return result;
+    },
+
+    _getRangeIcon: function(irange, turnOn) {
+      return turnOn ? irange.on || this.opt.starOn : irange.off || this.opt.starOff;
+    },
+
+    _getScoreByPosition: function(evt, icon) {
+      var score = parseInt(icon.alt || icon.getAttribute('data-alt'), 10);
+
+      if (this.opt.half) {
+        var
+          size    = methods._getWidth.call(this),
+          percent = parseFloat((evt.pageX - $(icon).offset().left) / size);
+
+        score = score - 1 + percent;
+      }
+
+      return score;
+    },
+
+    _getHint: function(score, evt) {
+      if (score !== 0 && !score) {
+        return this.opt.noRatedMsg;
+      }
+
+      var
+        decimal = methods._getFirstDecimal.call(this, score),
+        integer = Math.ceil(score),
+        group   = this.opt.hints[(integer || 1) - 1],
+        hint    = group,
+        set     = !evt || this.move;
+
+      if (this.opt.precision) {
+        if (set) {
+          decimal = decimal === 0 ? 9 : decimal - 1;
+        }
+
+        hint = group[decimal];
+      } else if (this.opt.halfShow || this.opt.half) {
+        decimal = set && decimal === 0 ? 1 : decimal > 5 ? 1 : 0;
+
+        hint = group[decimal];
+      }
+
+      return hint === '' ? '' : hint || score;
+    },
+
+    _getWidth: function() {
+      var width = this.stars[0].width || parseFloat(this.stars.eq(0).css('font-size'));
+
+      if (!width) {
+        methods._error.call(this, 'Could not get the icon width!');
+      }
+
+      return width;
+    },
+
+    _lock: function() {
+      var hint = methods._getHint.call(this, this.score.val());
+
+      this.style.cursor = '';
+      this.title        = hint;
+
+      this.score.prop('readonly', true);
+      this.stars.prop('title', hint);
+
+      if (this.cancel) {
+        this.cancel.hide();
+      }
+
+      this.self.data('readonly', true);
+    },
+
+    _nameForIndex: function(i) {
+      return this.opt.score && this.opt.score >= i ? 'starOn' : 'starOff';
+    },
+
+    _resetTitle: function(star) {
+      for (var i = 0; i < this.opt.number; i++) {
+        this.stars[i].title = methods._getHint.call(this, i + 1);
+      }
+    },
+
+     _roundHalfScore: function(score) {
+      var integer = parseInt(score, 10),
+          decimal = methods._getFirstDecimal.call(this, score);
+
+      if (decimal !== 0) {
+        decimal = decimal > 5 ? 1 : 0.5;
+      }
+
+      return integer + decimal;
+    },
+
+    _roundStars: function(score, evt) {
+      var
+        decimal = (score % 1).toFixed(2),
+        name    ;
+
+      if (evt || this.move) {
+        name = decimal > 0.5 ? 'starOn' : 'starHalf';
+      } else if (decimal > this.opt.round.down) {               // Up:   [x.76 .. x.99]
+        name = 'starOn';
+
+        if (this.opt.halfShow && decimal < this.opt.round.up) { // Half: [x.26 .. x.75]
+          name = 'starHalf';
+        } else if (decimal < this.opt.round.full) {             // Down: [x.00 .. x.5]
+          name = 'starOff';
+        }
+      }
+
+      if (name) {
+        var
+          icon = this.opt[name],
+          star = this.stars[Math.ceil(score) - 1];
+
+        methods._setIcon.call(this, star, icon);
+      }                                                         // Full down: [x.00 .. x.25]
+    },
+
+    _setIcon: function(star, icon) {
+      star[this.opt.starType === 'img' ? 'src' : 'className'] = this.opt.path + icon;
+    },
+
+    _setTarget: function(target, score) {
+      if (score) {
+        score = this.opt.targetFormat.toString().replace('{score}', score);
+      }
+
+      if (target.is(':input')) {
+        target.val(score);
+      } else {
+        target.html(score);
+      }
+    },
+
+    _setTitle: function(score, evt) {
+      if (score) {
+        var
+          integer = parseInt(Math.ceil(score), 10),
+          star    = this.stars[integer - 1];
+
+        star.title = methods._getHint.call(this, score, evt);
+      }
+    },
+
+    _target: function(score, evt) {
+      if (this.opt.target) {
+        var target = $(this.opt.target);
+
+        if (!target.length) {
+          methods._error.call(this, 'Target selector invalid or missing!');
+        }
+
+        var mouseover = evt && evt.type === 'mouseover';
+
+        if (score === undefined) {
+          score = this.opt.targetText;
+        } else if (score === null) {
+          score = mouseover ? this.opt.cancelHint : this.opt.targetText;
+        } else {
+          if (this.opt.targetType === 'hint') {
+            score = methods._getHint.call(this, score, evt);
+          } else if (this.opt.precision) {
+            score = parseFloat(score).toFixed(1);
+          }
+
+          var mousemove = evt && evt.type === 'mousemove';
+
+          if (!mouseover && !mousemove && !this.opt.targetKeep) {
+            score = this.opt.targetText;
+          }
+        }
+
+        methods._setTarget.call(this, target, score);
+      }
+    },
+
+    _turnOn: function(i, score) {
+      return this.opt.single ? (i === score) : (i <= score);
+    },
+
+    _unlock: function() {
+      this.style.cursor = 'pointer';
+      this.removeAttribute('title');
+
+      this.score.removeAttr('readonly');
+
+      this.self.data('readonly', false);
+
+      for (var i = 0; i < this.opt.number; i++) {
+        this.stars[i].title = methods._getHint.call(this, i + 1);
+      }
+
+      if (this.cancel) {
+        this.cancel.css('display', '');
+      }
+    },
+
+    cancel: function(click) {
+      return this.each(function() {
+        var self = $(this);
+
+        if (self.data('readonly') !== true) {
+          methods[click ? 'click' : 'score'].call(self, null);
+
+          this.score.removeAttr('value');
+        }
+      });
+    },
+
+    click: function(score) {
+      return this.each(function() {
+        if ($(this).data('readonly') !== true) {
+          score = methods._adjustedScore.call(this, score);
+
+          methods._apply.call(this, score);
+
+          if (this.opt.click) {
+            this.opt.click.call(this, score, $.Event('click'));
+          }
+
+          methods._target.call(this, score);
+        }
+      });
+    },
+
+    destroy: function() {
+      return this.each(function() {
+        var self = $(this),
+            raw  = self.data('raw');
+
+        if (raw) {
+          self.off('.raty').empty().css({ cursor: raw.style.cursor }).removeData('readonly');
+        } else {
+          self.data('raw', self.clone()[0]);
+        }
+      });
+    },
+
+    getScore: function() {
+      var score = [],
+          value ;
+
+      this.each(function() {
+        value = this.score.val();
+
+        score.push(value ? +value : undefined);
+      });
+
+      return (score.length > 1) ? score : score[0];
+    },
+
+    move: function(score) {
+      return this.each(function() {
+        var
+          integer  = parseInt(score, 10),
+          decimal  = methods._getFirstDecimal.call(this, score);
+
+        if (integer >= this.opt.number) {
+          integer = this.opt.number - 1;
+          decimal = 10;
+        }
+
+        var
+          width   = methods._getWidth.call(this),
+          steps   = width / 10,
+          star    = $(this.stars[integer]),
+          percent = star.offset().left + steps * decimal,
+          evt     = $.Event('mousemove', { pageX: percent });
+
+        this.move = true;
+
+        star.trigger(evt);
+
+        this.move = false;
+      });
+    },
+
+    readOnly: function(readonly) {
+      return this.each(function() {
+        var self = $(this);
+
+        if (self.data('readonly') !== readonly) {
+          if (readonly) {
+            self.off('.raty').children(this.opt.starType).off('.raty');
+
+            methods._lock.call(this);
+          } else {
+            methods._binds.call(this);
+            methods._unlock.call(this);
+          }
+
+          self.data('readonly', readonly);
+        }
+      });
+    },
+
+    reload: function() {
+      return methods.set.call(this, {});
+    },
+
+    score: function() {
+      var self = $(this);
+
+      return arguments.length ? methods.setScore.apply(self, arguments) : methods.getScore.call(self);
+    },
+
+    set: function(options) {
+      return this.each(function() {
+        $(this).raty($.extend({}, this.opt, options));
+      });
+    },
+
+    setScore: function(score) {
+      return this.each(function() {
+        if ($(this).data('readonly') !== true) {
+          score = methods._adjustedScore.call(this, score);
+
+          methods._apply.call(this, score);
+          methods._target.call(this, score);
+        }
+      });
+    }
+  };
+
+  $.fn.raty = function(method) {
+    if (methods[method]) {
+      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+    } else if (typeof method === 'object' || !method) {
+      return methods.init.apply(this, arguments);
+    } else {
+      $.error('Method ' + method + ' does not exist!');
+    }
+  };
+
+  $.fn.raty.defaults = {
+    cancel       : false,
+    cancelClass  : 'raty-cancel',
+    cancelHint   : 'Cancel this rating!',
+    cancelOff    : 'cancel-off.png',
+    cancelOn     : 'cancel-on.png',
+    cancelPlace  : 'left',
+    click        : undefined,
+    half         : false,
+    halfShow     : true,
+    hints        : ['bad', 'poor', 'regular', 'good', 'gorgeous'],
+    iconRange    : undefined,
+    mouseout     : undefined,
+    mouseover    : undefined,
+    noRatedMsg   : 'Not rated yet!',
+    number       : 5,
+    numberMax    : 20,
+    path         : undefined,
+    precision    : false,
+    readOnly     : false,
+    round        : { down: 0.25, full: 0.6, up: 0.76 },
+    score        : undefined,
+    scoreName    : 'score',
+    single       : false,
+    space        : true,
+    starHalf     : 'star-half.png',
+    starOff      : 'star-off.png',
+    starOn       : 'star-on.png',
+    starType     : 'img',
+    target       : undefined,
+    targetFormat : '{score}',
+    targetKeep   : false,
+    targetScore  : undefined,
+    targetText   : '',
+    targetType   : 'hint'
+  };
+
+})(jQuery);
diff --git a/sweettooth/static/js/main.js b/sweettooth/static/js/main.js
index 98ed0a8..424f8da 100644
--- a/sweettooth/static/js/main.js
+++ b/sweettooth/static/js/main.js
@@ -96,15 +96,29 @@ function($, messages, modal, hashParamUtils, templates) {
         $.fn.ratify = function() {
             return this.each(function() {
                 $(this).raty({
-                    start: $(this).data('rating-value'),
+                    score: $(this).data('rating-value'),
                     readOnly: true
                 });
             });
         };
 
+        let rating_initial = $('#rating_form').find('input[name="rating_initial"]');
+
         $('.comment .rating').ratify();
-        $('#rating_form').hide();
-        $('#rating_form .rating').raty({ scoreName: 'rating' });
+        $('#rating_form:not(.preview)').hide();
+        $('#rating_form .rating').raty({
+            scoreName: 'rating',
+            score: rating_initial.length > 0 ? rating_initial.val() : undefined
+        });
+
+        if($('#rating_form input[name="show_rating"]').val() == '1')
+        {
+            $('#rating_form').find('.rating').show();
+        }
+        else
+        {
+            $('#rating_form').find('.rating').hide();
+        }
 
         function makeShowForm(isRating) {
             return function() {
@@ -112,9 +126,15 @@ function($, messages, modal, hashParamUtils, templates) {
                 $(this).addClass('selected');
                 var $rating = $('#rating_form').slideDown().find('.rating');
                 if (isRating)
-                    $rating.show();
+                               {
+                                       $rating.show();
+                                       $('#rating_form input[name="show_rating"]').val('1');
+                               }
                 else
-                    $rating.hide();
+                               {
+                                       $rating.hide();
+                                       $('#rating_form input[name="show_rating"]').val('0');
+                               }
             };
         }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]