This is an automated email from the git hooks/post-receive script. New commit to branch feature/R7776-cloudTags-in-homepage in repository coselmar. See http://git.codelutin.com/coselmar.git commit 3f4d90b5b2416d830c3063c5a895b09f66a71aaa Author: Yannick Martel <martel@©odelutin.com> Date: Wed Dec 16 16:24:48 2015 +0100 refs-80 #7776 mise en plac du nuage de mot sur l'ui --- coselmar-ui/pom.xml | 6 + coselmar-ui/src/main/webapp/css/jqcloud-2.0.0.css | 59 +++ coselmar-ui/src/main/webapp/index.html | 8 + coselmar-ui/src/main/webapp/js/angular-jqcloud.js | 59 +++ .../src/main/webapp/js/coselmar-controllers.js | 10 +- .../main/webapp/js/coselmar-general-services.js | 43 ++ coselmar-ui/src/main/webapp/js/coselmar.js | 2 +- coselmar-ui/src/main/webapp/js/jqcloud-2.0.0.js | 528 +++++++++++++++++++++ coselmar-ui/src/main/webapp/views/home.html | 5 + pom.xml | 8 + 10 files changed, 726 insertions(+), 2 deletions(-) diff --git a/coselmar-ui/pom.xml b/coselmar-ui/pom.xml index 39622e7..10ae37c 100644 --- a/coselmar-ui/pom.xml +++ b/coselmar-ui/pom.xml @@ -93,6 +93,12 @@ <scope>runtime</scope> </dependency> + <!--<dependency>--> + <!--<groupId>org.webjars.bower</groupId>--> + <!--<artifactId>jqcloud2</artifactId>--> + <!--<scope>runtime</scope>--> + <!--</dependency>--> + </dependencies> <build> diff --git a/coselmar-ui/src/main/webapp/css/jqcloud-2.0.0.css b/coselmar-ui/src/main/webapp/css/jqcloud-2.0.0.css new file mode 100644 index 0000000..3f276ed --- /dev/null +++ b/coselmar-ui/src/main/webapp/css/jqcloud-2.0.0.css @@ -0,0 +1,59 @@ +/* + * #%L + * ! + * jQCloud + * Copyright 2011 Luca Ongaro (http://www.lucaongaro.eu) + * Copyright 2013 Daniel White (http://www.developerdan.com) + * Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * Licensed under MIT (http://opensource.org/licenses/MIT) + * #L% + */ + +/* layout */ +div.jqcloud { + overflow: hidden; + position: relative; +} + +div.jqcloud span { + padding: 0; +} + +/* fonts */ +div.jqcloud { + font-family: "Helvetica", "Arial", sans-serif; + font-size: 10px; + line-height: normal; +} + +div.jqcloud a { + font-size: inherit; + text-decoration: none; +} + +div.jqcloud span.w10 { font-size: 550%; } +div.jqcloud span.w9 { font-size: 500%; } +div.jqcloud span.w8 { font-size: 450%; } +div.jqcloud span.w7 { font-size: 400%; } +div.jqcloud span.w6 { font-size: 350%; } +div.jqcloud span.w5 { font-size: 300%; } +div.jqcloud span.w4 { font-size: 250%; } +div.jqcloud span.w3 { font-size: 200%; } +div.jqcloud span.w2 { font-size: 150%; } +div.jqcloud span.w1 { font-size: 100%; } + +/* colors */ +div.jqcloud { color: #09f; } +div.jqcloud a { color: inherit; } +div.jqcloud a:hover { color: #0df; } +div.jqcloud a:hover { color: #0cf; } +div.jqcloud span.w10 { color: #0cf; } +div.jqcloud span.w9 { color: #0cf; } +div.jqcloud span.w8 { color: #0cf; } +div.jqcloud span.w7 { color: #39d; } +div.jqcloud span.w6 { color: #90c5f0; } +div.jqcloud span.w5 { color: #90a0dd; } +div.jqcloud span.w4 { color: #90c5f0; } +div.jqcloud span.w3 { color: #a0ddff; } +div.jqcloud span.w2 { color: #99ccee; } +div.jqcloud span.w1 { color: #aab5f0; } \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/index.html b/coselmar-ui/src/main/webapp/index.html index f5e6678..ce47b70 100644 --- a/coselmar-ui/src/main/webapp/index.html +++ b/coselmar-ui/src/main/webapp/index.html @@ -30,6 +30,8 @@ <link rel="stylesheet" href="webjars/angular-notify/2.5.0/angular-notify.min.css"> <link rel="stylesheet" href="webjars/bootstrap/3.3.6/css/bootstrap.css"> <link rel="stylesheet" href="webjars/font-awesome/4.5.0/css/font-awesome.css"> + <link rel="stylesheet" href="webjars/jqcloud2/2.0.1/jqcloud/jqcloud.css"> + <link rel="stylesheet" href="css/jqcloud-2.0.0.css"> <link rel="stylesheet" href="css/coselmar.css"> <script src="webjars/jquery/2.1.4/jquery.js"></script> @@ -50,14 +52,20 @@ <link rel="stylesheet" href="webjars/angular-ui-select/0.13.1/select.css"> <script src="webjars/angular-ui-bootstrap/0.14.3/ui-bootstrap.js"></script> <script src="webjars/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.js"></script> + <script src="webjars/jqcloud2/2.0.1/jqcloud/jqcloud-2.0.1.js"></script> + <script src="js/jqcloud-2.0.0.js"></script> <script src="js/angular-jwt.js"></script> + <script src="js/angular-jqcloud.js"></script> + <script src="i18n/en.js"></script> <script src="i18n/fr.js"></script> + <script src="js/coselmar.js"></script> <script src="js/coselmar-constants.js"></script> <script src="js/coselmar-controllers.js"></script> <script src="js/coselmar-services.js"></script> + <script src="js/coselmar-general-services.js"></script> <script src="js/coselmar-user-services.js"></script> <script src="js/coselmar-questions-services.js"></script> <script src="js/coselmar-admin-services.js"></script> diff --git a/coselmar-ui/src/main/webapp/js/angular-jqcloud.js b/coselmar-ui/src/main/webapp/js/angular-jqcloud.js new file mode 100644 index 0000000..8a02bd0 --- /dev/null +++ b/coselmar-ui/src/main/webapp/js/angular-jqcloud.js @@ -0,0 +1,59 @@ +/*! + * #%L + * Angular jQCloud 1.0.2 + * For jQCloud 2 (https://github.com/mistic100/jQCloud) + * Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * Licensed under MIT (http://opensource.org/licenses/MIT) + * #L% + */ + +angular.module('angular-jqcloud', []).directive('jqcloud', ['$parse', function($parse) { + // get existing options + var defaults = jQuery.fn.jQCloud.defaults.get(), + jqcOptions = []; + + for (var opt in defaults) { + if (defaults.hasOwnProperty(opt)) { + jqcOptions.push(opt); + } + } + + return { + restrict: 'E', + template: '<div></div>', + replace: true, + scope: { + words: '=words', + afterCloudRender: '&' + }, + link: function($scope, $elem, $attr) { + var options = {}; + + for (var i=0, l=jqcOptions.length; i<l; i++) { + var opt = jqcOptions[i]; + var attr = $attr[opt] || $elem.attr(opt); + if (attr !== undefined) { + options[opt] = $parse(attr)(); + } + } + + if ($scope.afterCloudRender) { + options.afterCloudRender = $scope.afterCloudRender; + } + + jQuery($elem).jQCloud($scope.words, options); + + $scope.$watchCollection('words', function() { + $scope.$evalAsync(function() { + var words = []; + $.extend(words,$scope.words); + jQuery($elem).jQCloud('update', words); + }); + }); + + $elem.bind('$destroy', function() { + jQuery($elem).jQCloud('destroy'); + }); + } + }; +}]); \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 0f40bf1..c8ba720 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -115,9 +115,10 @@ coselmarControllers.controller("unauthorizedCtrl", ['$scope', '$location', funct }]); // Controller for home when user connected, load 5 last projects -coselmarControllers.controller("homeConnectedCtrl", ['$scope', 'questionsService', function ($scope, questionsService) { +coselmarControllers.controller("homeConnectedCtrl", ['$scope', 'questionsService', 'generalService', function ($scope, questionsService, generalService) { $scope.closedQuestions = []; + $scope.topWords = [{text:"coselmar", weight: 10}, {text: "Ifremer", weight: 5}]; if ($scope.context && $scope.context.currentUser) { @@ -145,6 +146,13 @@ coselmarControllers.controller("homeConnectedCtrl", ['$scope', 'questionsService }); } + generalService.getTopWords(function(result) { + $scope.topWords = result.data; + }, function(fail) { + $scope.topWords = []; + }); + + }]); ///////////////////////////////////////////////// diff --git a/coselmar-ui/src/main/webapp/js/coselmar-general-services.js b/coselmar-ui/src/main/webapp/js/coselmar-general-services.js new file mode 100644 index 0000000..def2091 --- /dev/null +++ b/coselmar-ui/src/main/webapp/js/coselmar-general-services.js @@ -0,0 +1,43 @@ +/* + * #%L + * Coselmar :: UI + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Ifremer, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +coselmarServices.factory('generalService', ['$http', 'coselmar-config', function($http, coselmarConfig){ + return new GeneralService($http, coselmarConfig); +}]); + +function GeneralService(http, config){ + + this.http = http; + + var baseURL = config.BASE_URL + "/general"; + + this.getTopWords = function(successFunction, failFunction) { + + var topWordsUrl = baseURL + "/topwords"; + + http.get(topWordsUrl).then(successFunction, failFunction); + + }; + +}; \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/js/coselmar.js b/coselmar-ui/src/main/webapp/js/coselmar.js index d5b7b22..8904db3 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar.js +++ b/coselmar-ui/src/main/webapp/js/coselmar.js @@ -23,7 +23,7 @@ */ var coselmarApp = angular.module("coselmarApp", ['ngRoute', 'ngResource', 'ngMessages', 'ngAnimate', 'pascalprecht.translate', 'tmh.dynamicLocale', 'cgNotify', - 'angular-jwt', 'coselmarControllers', 'coselmarServices']); + 'angular-jwt', 'angular-jqcloud', 'coselmarControllers', 'coselmarServices']); coselmarApp.config(['$routeProvider', function($routeProvider) { $routeProvider diff --git a/coselmar-ui/src/main/webapp/js/jqcloud-2.0.0.js b/coselmar-ui/src/main/webapp/js/jqcloud-2.0.0.js new file mode 100644 index 0000000..5c9cc4f --- /dev/null +++ b/coselmar-ui/src/main/webapp/js/jqcloud-2.0.0.js @@ -0,0 +1,528 @@ +/* + * #%L + * ! + * jQCloud + * Copyright 2011 Luca Ongaro (http://www.lucaongaro.eu) + * Copyright 2013 Daniel White (http://www.developerdan.com) + * Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr) + * Licensed under MIT (http://opensource.org/licenses/MIT) + * #L% + */ + +/*jshint -W055 *//* non standard constructor name */ + +(function($) { + "use strict"; + + /* + * Plugin class + */ + var jQCloud = function (element, word_array, options) { + this.$element = $(element); + + this.word_array = word_array || []; + this.options = options; + + this.sizeGenerator = null; + this.colorGenerator = null; + + // Data used internally + this.data = { + placed_words: [], + timeouts: {}, + namespace: null, + step: null, + angle: null, + aspect_ratio: null, + max_weight: null, + min_weight: null, + sizes: [], + colors: [] + }; + + this.initialize(); + }; + + jQCloud.DEFAULTS = { + width: 100, + height: 100, + center: { x: 0.5, y: 0.5 }, + steps: 10, + delay: null, + shape: 'elliptic', + classPattern: 'w{n}', + encodeURI: true, + removeOverflowing: true, + afterCloudRender: null, + autoResize: false, + colors: null, + fontSize: null, + template: null + }; + + jQCloud.prototype = { + initialize: function() { + // Set/Get dimensions + if (this.options.width) { + this.$element.width(this.options.width); + } + else { + this.options.width = this.$element.width(); + } + if (this.options.height) { + this.$element.height(this.options.height); + } + else { + this.options.height = this.$element.height(); + } + + // Default options value + this.options = $.extend(true, {}, jQCloud.DEFAULTS, this.options); + + // Ensure delay + if (this.options.delay === null) { + this.options.delay = this.word_array.length > 50 ? 10 : 0; + } + + // Backward compatibility + if (this.options.center.x > 1) { + this.options.center.x = this.options.center.x / this.options.width; + this.options.center.y = this.options.center.y / this.options.height; + } + + // Create colorGenerator function from options + // Direct function + if (typeof this.options.colors == 'function') { + this.colorGenerator = this.options.colors; + } + // Array of sizes + else if ($.isArray(this.options.colors)) { + var cl = this.options.colors.length; + if (cl > 0) { + // Fill the sizes array to X items + if (cl < this.options.steps) { + for (var i=cl; i<this.options.steps; i++) { + this.options.colors[i] = this.options.colors[cl-1]; + } + } + + this.colorGenerator = function(weight) { + return this.options.colors[this.options.steps - weight]; + }; + } + } + + // Create sizeGenerator function from options + // Direct function + if (typeof this.options.fontSize == 'function') { + this.sizeGenerator = this.options.fontSize; + } + // Object with 'from' and 'to' + else if ($.isPlainObject(this.options.fontSize)) { + this.sizeGenerator = function(width, height, weight) { + var max = width * this.options.fontSize.from, + min = width * this.options.fontSize.to; + return Math.round(min + (max - min) * 1.0 / (this.options.steps-1) * (weight - 1)) + 'px'; + }; + } + // Array of sizes + else if ($.isArray(this.options.fontSize)) { + var sl = this.options.fontSize.length; + if (sl > 0) { + // Fill the sizes array to X items + if (sl < this.options.steps) { + for (var j=sl; j<this.options.steps; j++) { + this.options.fontSize[j] = this.options.fontSize[sl-1]; + } + } + + this.sizeGenerator = function(width, height, weight) { + return this.options.fontSize[this.options.steps - weight]; + }; + } + } + + this.data.angle = Math.random() * 6.28; + this.data.step = (this.options.shape === 'rectangular') ? 18.0 : 2.0; + this.data.aspect_ratio = this.options.width / this.options.height; + this.clearTimeouts(); + + // Namespace word ids to avoid collisions between multiple clouds + this.data.namespace = (this.$element.attr('id') || Math.floor((Math.random()*1000000)).toString(36)) + '_word_'; + + this.$element.addClass('jqcloud'); + + // Container's CSS position cannot be 'static' + if (this.$element.css('position') === 'static') { + this.$element.css('position', 'relative'); + } + + // Delay execution so that the browser can render the page before the computatively intensive word cloud drawing + this.createTimeout($.proxy(this.drawWordCloud, this), 10); + + // Attach window resize event + if (this.options.autoResize) { + $(window).on('resize', throttle(function() { + var new_size = { + width: this.$element.width(), + height: this.$element.height() + }; + + if (new_size.width != this.options.width || new_size.height != this.options.height) { + this.options.width = new_size.width; + this.options.height = new_size.height; + this.data.aspect_ratio = this.options.width / this.options.height; + + this.update(this.word_array); + } + }, 50, this)); + } + }, + + // Helper function to keep track of timeouts so they can be destroyed + createTimeout: function(callback, time) { + var timeout = setTimeout($.proxy(function(){ + delete this.data.timeouts[timeout]; + callback(); + }, this), time); + this.data.timeouts[timeout] = true; + }, + + // Destroy all timeouts + clearTimeouts: function() { + $.each(this.data.timeouts, function(key){ + clearTimeout(key); + }); + this.data.timeouts = {}; + }, + + // Pairwise overlap detection + overlapping: function(a, b) { + if (Math.abs(2.0*a.left + a.width - 2.0*b.left - b.width) < a.width + b.width) { + if (Math.abs(2.0*a.top + a.height - 2.0*b.top - b.height) < a.height + b.height) { + return true; + } + } + return false; + }, + + // Helper function to test if an element overlaps others + hitTest: function(elem) { + // Check elements for overlap one by one, stop and return false as soon as an overlap is found + for(var i=0, l=this.data.placed_words.length; i<l; i++) { + if (this.overlapping(elem, this.data.placed_words[i])) { + return true; + } + } + return false; + }, + + // Initialize the drawing of the whole cloud + drawWordCloud: function() { + var i, l; + + this.$element.children('[id^="' + this.data.namespace + '"]').remove(); + + if (this.word_array.length === 0) { + return; + } + + // Make sure every weight is a number before sorting + for (i=0, l=this.word_array.length; i<l; i++) { + this.word_array[i].weight = parseFloat(this.word_array[i].weight, 10); + } + + // Sort word_array from the word with the highest weight to the one with the lowest + this.word_array.sort(function(a, b) { + return b.weight - a.weight; + }); + + // Kepp trace of bounds + this.data.max_weight = this.word_array[0].weight; + this.data.min_weight = this.word_array[this.word_array.length - 1].weight; + + // Generate colors + this.data.colors = []; + if (this.colorGenerator) { + for (i=0; i<this.options.steps; i++) { + this.data.colors.push(this.colorGenerator(i+1)); + } + } + + // Generate font sizes + this.data.sizes = []; + if (this.sizeGenerator) { + for (i=0; i<this.options.steps; i++) { + this.data.sizes.push(this.sizeGenerator(this.options.width, this.options.height, i+1)); + } + } + + // Iterate drawOneWord on every word, immediately or with delay + if (this.options.delay > 0){ + this.drawOneWordDelayed(); + } + else { + for (i=0, l=this.word_array.length; i<l; i++) { + this.drawOneWord(i, this.word_array[i]); + } + + if (typeof this.options.afterCloudRender === 'function') { + this.options.afterCloudRender.call(this.$element); + } + } + }, + + // Function to draw a word, by moving it in spiral until it finds a suitable empty place + drawOneWord: function(index, word) { + var word_id = this.data.namespace + index, + word_selector = '#' + word_id, + + // option.shape == 'elliptic' + angle = this.data.angle, + radius = 0.0, + + // option.shape == 'rectangular' + steps_in_direction = 0.0, + quarter_turns = 0.0, + + weight = Math.floor(this.options.steps / 2), + word_span, + word_size, + word_style; + + // Create word attr object + word.attr = $.extend({}, word.html, { id: word_id }); + + // Linearly map the original weight to a discrete scale from 1 to 10 + // Only if weights are different + if (this.data.max_weight != this.data.min_weight) { + weight = Math.round((word.weight - this.data.min_weight) * 1.0 * (this.options.steps-1) / (this.data.max_weight - this.data.min_weight)) + 1; + } + word_span = $('<span>').attr(word.attr); + + // Apply class + if (this.options.classPattern) { + word_span.addClass(this.options.classPattern.replace('{n}', weight)); + } + + // Apply color + if (this.data.colors.length) { + word_span.css('color', this.data.colors[weight-1]); + } + + // Apply size + if (this.data.sizes.length) { + word_span.css('font-size', this.data.sizes[weight-1]); + } + + //Render using template function if provided. + if (this.options.template) { + word_span.html(this.options.template(word)); + } else if (word.link) { + // Append link if word.link attribute was set + // If link is a string, then use it as the link href + if (typeof word.link === 'string') { + word.link = { href: word.link }; + } + + if (this.options.encodeURI) { + word.link.href = encodeURI(word.link.href).replace(/'/g, '%27'); + } + + word_span.append($('<a>').attr(word.link).text(word.text)); + } + else { + word_span.text(word.text); + } + + // Bind handlers to words + if (word.handlers) { + word_span.on(word.handlers); + } + + this.$element.append(word_span); + + word_size = { + width: word_span.outerWidth(), + height: word_span.outerHeight() + }; + word_size.left = this.options.center.x*this.options.width - word_size.width / 2.0; + word_size.top = this.options.center.y*this.options.height - word_size.height / 2.0; + + // Save a reference to the style property, for better performance + word_style = word_span[0].style; + word_style.position = 'absolute'; + word_style.left = word_size.left + 'px'; + word_style.top = word_size.top + 'px'; + + while(this.hitTest(word_size)) { + // option shape is 'rectangular' so move the word in a rectangular spiral + if (this.options.shape === 'rectangular') { + steps_in_direction++; + + if (steps_in_direction * this.data.step > (1 + Math.floor(quarter_turns / 2.0)) * this.data.step * ((quarter_turns % 4 % 2) === 0 ? 1 : this.data.aspect_ratio)) { + steps_in_direction = 0.0; + quarter_turns++; + } + + switch(quarter_turns % 4) { + case 1: + word_size.left += this.data.step * this.data.aspect_ratio + Math.random() * 2.0; + break; + case 2: + word_size.top -= this.data.step + Math.random() * 2.0; + break; + case 3: + word_size.left -= this.data.step * this.data.aspect_ratio + Math.random() * 2.0; + break; + case 0: + word_size.top += this.data.step + Math.random() * 2.0; + break; + } + } + // Default settings: elliptic spiral shape + else { + radius += this.data.step; + angle += (index % 2 === 0 ? 1 : -1) * this.data.step; + + word_size.left = this.options.center.x*this.options.width - (word_size.width / 2.0) + (radius*Math.cos(angle)) * this.data.aspect_ratio; + word_size.top = this.options.center.y*this.options.height + radius*Math.sin(angle) - (word_size.height / 2.0); + } + word_style.left = word_size.left + 'px'; + word_style.top = word_size.top + 'px'; + } + + // Don't render word if part of it would be outside the container + if (this.options.removeOverflowing && ( + word_size.left < 0 || word_size.top < 0 || + (word_size.left + word_size.width) > this.options.width || + (word_size.top + word_size.height) > this.options.height + ) + ) { + word_span.remove(); + return; + } + + // Save position for further usage + this.data.placed_words.push(word_size); + + if (typeof word.afterWordRender === 'function') { + word.afterWordRender.call(word_span); + } + }, + + // Draw one word then recall the function after a delay + drawOneWordDelayed: function(index) { + index = index || 0; + + // if not visible then do not attempt to draw + if (!this.$element.is(':visible')) { + this.createTimeout($.proxy(function(){ + this.drawOneWordDelayed(index); + }, this), 10); + + return; + } + + if (index < this.word_array.length) { + this.drawOneWord(index, this.word_array[index]); + + this.createTimeout($.proxy(function(){ + this.drawOneWordDelayed(index + 1); + }, this), this.options.delay); + } + else { + if (typeof this.options.afterCloudRender == 'function') { + this.options.afterCloudRender.call(this.$element); + } + } + }, + + // Destroy any data and objects added by the plugin + destroy: function() { + this.clearTimeouts(); + this.$element.removeClass('jqcloud'); + this.$element.removeData('jqcloud'); + this.$element.children('[id^="' + this.data.namespace + '"]').remove(); + }, + + // Update the list of words + update: function(word_array) { + this.word_array = word_array; + this.data.placed_words = []; + + this.clearTimeouts(); + this.drawWordCloud(); + } + }; + + /* + * Apply throttling to a callback + * @param callback {function} + * @param delay {int} milliseconds + * @param context {object|null} + * @return {function} + */ + function throttle(callback, delay, context) { + var state = { + pid: null, + last: 0 + }; + + return function() { + var elapsed = new Date().getTime() - state.last, + args = arguments, + that = this; + + function exec() { + state.last = new Date().getTime(); + return callback.apply(context || that, Array.prototype.slice.call(args)); + } + + if (elapsed > delay) { + return exec(); + } + else { + clearTimeout(state.pid); + state.pid = setTimeout(exec, delay - elapsed); + } + }; + } + + /* + * jQuery plugin + */ + $.fn.jQCloud = function(word_array, option) { + var args = arguments; + + return this.each(function () { + var $this = $(this), + data = $this.data('jqcloud'); + + if (!data && word_array === 'destroy') { + // Don't even try to initialize when called with 'destroy' + return; + } + if (!data) { + var options = typeof option === 'object' ? option : {}; + $this.data('jqcloud', (data = new jQCloud(this, word_array, options))); + } + else if (typeof word_array === 'string') { + data[word_array].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + $.fn.jQCloud.defaults = { + set: function(options) { + $.extend(true, jQCloud.DEFAULTS, options); + }, + get: function(key) { + var options = jQCloud.DEFAULTS; + if (key) { + options = options[key]; + } + return $.extend(true, {}, options); + } + }; +})(jQuery); \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/views/home.html b/coselmar-ui/src/main/webapp/views/home.html index f11dc65..01e1c61 100644 --- a/coselmar-ui/src/main/webapp/views/home.html +++ b/coselmar-ui/src/main/webapp/views/home.html @@ -110,4 +110,9 @@ </table> <p ng-if="questions && questions.length == 0" translate="common.search.noResult" class="info"/> </div> + + <!-- FIXME Leo #CSS --> + <div align="center"> + <jqcloud words="topWords" width="500" height="350" steps="21" font-size="{from:0.09, to:0.04}"></jqcloud> + </div> </div> diff --git a/pom.xml b/pom.xml index f8b4d12..f68d67a 100644 --- a/pom.xml +++ b/pom.xml @@ -166,6 +166,7 @@ <!-- XXX ymartel 20151202 : cannot upgrade httpcomponents deps for the moment, still needed for webmotion test --> <fluent-hc.version>4.2.3</fluent-hc.version> <httpcore.version>4.2.3</httpcore.version> + <jqcloud2Version>2.0.1</jqcloud2Version> </properties> <repositories> @@ -475,6 +476,13 @@ <scope>runtime</scope> </dependency> + <dependency> + <groupId>org.webjars.bower</groupId> + <artifactId>jqcloud2</artifactId> + <version>${jqcloud2Version}</version> + <scope>runtime</scope> + </dependency> + <!-- Others --> <dependency> <groupId>com.github.spullara.mustache.java</groupId> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.