awesome_tooltip 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bbfdec35a56aaf49f1fcfb538a16b48847bd6d13b92fff6f408373e83729b0ea
4
+ data.tar.gz: 26d65c37724f84882a20eaf6377b68b25cc1afa0a73be717163ce84fb168a16f
5
+ SHA512:
6
+ metadata.gz: 43be165f360c59ecf5faf1b19035f88b9f2d8dc4334d3b51cf6c7ea94f59ff0ec8f609a72e57864fb8e8be927275923864ccd283405e69138a5d6710794c2a1b
7
+ data.tar.gz: 48be87c03ea8f7ffb28145629efeceae8884d7f4628fa5d03e8b182c8977536e04c4f8edf34a59ad6de8d0c46a03ce969a067c235aa241564149c033e6441410
@@ -0,0 +1,20 @@
1
+ Copyright 2019 Busko Bogdan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # AwesomeTooltip
2
+ [![Build Status](https://travis-ci.com/BogdanBusko/awesome_tooltip.svg?branch=master)](https://travis-ci.com/BogdanBusko/awesome_tooltip)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/13a8f6106b17b50e9943/maintainability)](https://codeclimate.com/github/BogdanBusko/awesome_tooltip/maintainability)
4
+
5
+ Short description and motivation.
6
+
7
+ ## Usage
8
+ How to use my plugin.
9
+
10
+ ## Installation
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'awesome_tooltip'
15
+ ```
16
+
17
+ And then execute:
18
+ ```bash
19
+ $ bundle
20
+ ```
21
+
22
+ Or install it yourself as:
23
+ ```bash
24
+ $ gem install awesome_tooltip
25
+ ```
26
+
27
+ ## Contributing
28
+ Contribution directions go here.
29
+
30
+ ## License
31
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AwesomeTooltip'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,148 @@
1
+ (function (W, D) {
2
+ var loadType;
3
+ var timerId;
4
+ var config = {
5
+ tooltipPath: "/tooltip/",
6
+ delay: 1500,
7
+ location: "top"
8
+ };
9
+
10
+ if(typeof(Turbolinks) !== undefined) {
11
+ loadType = "turbolinks:load";
12
+ } else {
13
+ loadType = "DOMContentLoaded";
14
+ }
15
+
16
+ function handleMouseEnter(element) {
17
+ element.addEventListener("mouseenter", function(e) {
18
+ clearTimeout(timerId);
19
+
20
+ if(e.currentTarget.getAttribute("data-template") && !e.currentTarget.querySelector(".awesome-tooltip")) {
21
+ fetchData(e.currentTarget);
22
+ }
23
+ });
24
+ }
25
+
26
+ function handleMouseLeave(element) {
27
+ element.addEventListener("mouseleave", function(e){
28
+ var tooltip = e.currentTarget.querySelector("." + e.currentTarget.className.split(" ").join(".") + " .awesome-tooltip");
29
+
30
+ timerId = setTimeout(function() {
31
+ if(tooltip)
32
+ tooltip.remove();
33
+ }, config.delay);
34
+ });
35
+ }
36
+
37
+ function tooltipPosition(element) {
38
+ var tooltip = element.querySelector(".awesome-tooltip");
39
+ var tooltipTriangle = tooltip.querySelector(".content-wrapper .triangle");
40
+ var elementRects = element.getClientRects()[0];
41
+
42
+ var leftEnoughSpace = tooltip.offsetWidth / 2 < elementRects.left;
43
+ var rightEnoughSpace = tooltip.offsetWidth / 2 < D.body.offsetWidth - elementRects.right;
44
+ var bottomEnoughSpace = tooltip.offsetHeight < W.height - elementRects.bottom;
45
+ var topEnoughSpace = tooltip.offsetHeight < elementRects.top;
46
+
47
+
48
+ if(leftEnoughSpace && rightEnoughSpace && topEnoughSpace && bottomEnoughSpace) {
49
+ tooltip.style.cssText = "left: " + ((elementRects.width / 2) - (tooltip.getClientRects()[0].width / 2)) + "px;";
50
+ tooltipTriangle.style.cssText = "left: calc(50% - " + (tooltipTriangle.offsetWidth / 2) + "px);";
51
+ return;
52
+ }
53
+
54
+ switch(element.getAttribute("data-location") || config.location) {
55
+ case "top":
56
+ case "bottom":
57
+ if(!topEnoughSpace && leftEnoughSpace && rightEnoughSpace) {
58
+ display(element, tooltipTriangle, "bottom");
59
+ break;
60
+ }
61
+
62
+ if(!bottomEnoughSpace && leftEnoughSpace && rightEnoughSpace) {
63
+ display(element, tooltipTriangle, "top");
64
+ break;
65
+ }
66
+
67
+ if(!topEnoughSpace) {
68
+ toggleLocation(tooltip, "bottom");
69
+ } else if(!bottomEnoughSpace) {
70
+ toggleLocation(tooltip, "top");
71
+ }
72
+
73
+ if(!leftEnoughSpace || !rightEnoughSpace) {
74
+ if(W.innerWidth / 2 > elementRects.right) {
75
+ tooltip.style.cssText = "left: -" + (elementRects.right - elementRects.left) + "px;";
76
+ tooltipTriangle.style.cssText = "left: " + (elementRects.right - elementRects.left + tooltipTriangle.offsetWidth + tooltipTriangle.offsetWidth / 2) + "px;";
77
+ } else {
78
+ tooltip.style.cssText = "right: -" + (D.body.offsetWidth - elementRects.right) + "px;";
79
+ tooltipTriangle.style.cssText = "right: " + (D.body.offsetWidth - elementRects.right + tooltipTriangle.offsetWidth + tooltipTriangle.offsetWidth / 2) + "px;";
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ function display(element, tooltipTriangle, location) {
86
+ var tooltip = element.querySelector(".awesome-tooltip");
87
+
88
+ toggleLocation(element, location);
89
+ tooltip.style.cssText = "left: " + ((element.getClientRects()[0].width / 2) - (tooltip.getClientRects()[0].width / 2)) + "px;";
90
+ tooltipTriangle.style.cssText = "left: calc(50% - " + (tooltipTriangle.offsetWidth / 2) + "px);";
91
+ }
92
+
93
+ function toggleLocation(element, location) {
94
+ element.className.replace(/top|bottom|left|right/gi, "").trim();
95
+ element.className += " " + location;
96
+ element.className.trim();
97
+ }
98
+
99
+ function tooltipTemplate(element, text) {
100
+ var elementLocation = element.getAttribute("data-location") || config.location;
101
+
102
+ element.insertAdjacentHTML("beforeend",
103
+ "<div class=\"awesome-tooltip " + elementLocation + "\">" +
104
+ "<div class=\"content-wrapper\">" +
105
+ "<div class=\"awesome-tooltip-text\">" + text + "</div>" +
106
+ "<div class=\"triangle\">" +
107
+ "</div>" +
108
+ "</div>"
109
+ );
110
+
111
+ tooltipPosition(element);
112
+ }
113
+
114
+ function fetchData(element) {
115
+ var url = W.location.origin;
116
+ var object = element.getAttribute("data-object") || "";
117
+ var tooltipPath = config.tooltipPath;
118
+
119
+ var req = new XMLHttpRequest();
120
+ req.open("GET", url + tooltipPath + element.getAttribute("data-template") + "/" + object);
121
+ req.onload = function() {
122
+ tooltipTemplate(element, req.response);
123
+ }
124
+ req.send();
125
+ }
126
+
127
+ D.addEventListener(loadType, function() {
128
+ var tooltips = D.querySelectorAll("[data-awesome-tooltip]");
129
+
130
+ tooltips.forEach(function(element) {
131
+ element.className += element.className.length < 1 ? "awesome-tooltip-wrapper" : " awesome-tooltip-wrapper";
132
+
133
+ handleMouseEnter(element);
134
+ handleMouseLeave(element);
135
+ });
136
+ });
137
+
138
+ function mergeConfigs(obj1, obj2){
139
+ var obj3 = {};
140
+ for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
141
+ for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
142
+ return obj3;
143
+ }
144
+
145
+ W.AwesomeTooltip = function(conf) {
146
+ config = mergeConfigs(config, conf);
147
+ }
148
+ })(window, document)
@@ -0,0 +1,70 @@
1
+ .awesome-tooltip-wrapper {
2
+ position: relative;
3
+
4
+ .awesome-tooltip {
5
+ position: absolute;
6
+ background-color: #fff;
7
+
8
+ &.hidden {
9
+ display: none;
10
+ }
11
+
12
+ &.top {
13
+ bottom: calc(100% + 15px);
14
+
15
+ .content-wrapper .triangle {
16
+ border-left: 10px solid transparent;
17
+ border-right: 10px solid transparent;
18
+ border-top: 10px solid #fff;
19
+ top: 100%;
20
+ }
21
+ }
22
+
23
+ &.bottom {
24
+ top: calc(100% + 15px);
25
+
26
+ .content-wrapper .triangle {
27
+ border-left: 10px solid transparent;
28
+ border-right: 10px solid transparent;
29
+ border-bottom: 10px solid #fff;
30
+ bottom: 100%;
31
+ }
32
+ }
33
+
34
+ &.left {
35
+ right: calc(100% + 15px);
36
+
37
+ .content-wrapper .triangle {
38
+ border-bottom: 10px solid transparent;
39
+ border-top: 10px solid transparent;
40
+ border-left: 10px solid #fff;
41
+ left: 100%;
42
+ }
43
+ }
44
+
45
+ &.right {
46
+ left: calc(100% + 15px);
47
+
48
+ .content-wrapper .triangle {
49
+ border-bottom: 10px solid transparent;
50
+ border-top: 10px solid transparent;
51
+ border-right: 10px solid #fff;
52
+ right: 100%;
53
+ }
54
+ }
55
+
56
+ .content-wrapper {
57
+ position: relative;
58
+ box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
59
+ padding: 5px 10px;
60
+ border-radius: 5px;
61
+
62
+ .triangle {
63
+ position: absolute;
64
+ width: 0;
65
+ height: 0;
66
+ z-index: 3;
67
+ }
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,2 @@
1
+ class AwesomeTooltip::ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,21 @@
1
+ class AwesomeTooltip::TooltipsController < ApplicationController
2
+ prepend_view_path(Rails.root.join('app', 'awesome_tooltips'))
3
+
4
+ def show
5
+ render template: params[:template], locals: { object: record }, layout: false
6
+ end
7
+
8
+ private
9
+
10
+ def attrs
11
+ params[:object].split('-')
12
+ end
13
+
14
+ def model
15
+ attrs[0].classify.constantize
16
+ end
17
+
18
+ def record
19
+ model.find(attrs[1]) if params[:object].present?
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ AwesomeTooltip::Engine.routes do
2
+ get '/tooltip/:template/(:object)' => 'tooltips#show', as: :tooltip
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'awesome_tooltip/railtie'
2
+ require 'awesome_tooltip/engine'
3
+
4
+ module AwesomeTooltip
5
+ end
@@ -0,0 +1,16 @@
1
+ module AwesomeTooltip
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace AwesomeTooltip
4
+
5
+ initializer 'awesome_tooltip.assets_precompile', group: :all do |app|
6
+ app.config.assets.precompile += [
7
+ 'awesome_tooltip/tooltip.js',
8
+ 'awesome_tooltip/tooltip.scss'
9
+ ]
10
+ end
11
+
12
+ initializer "sample_engine.factories", after: "factory_bot.set_factory_paths" do
13
+ FactoryBot.definition_file_paths << File.expand_path('../../../spec/factories', __FILE__) if defined?(FactoryBot)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module AwesomeTooltip
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module AwesomeTooltip
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awesome_tooltip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Busko Bogdan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sass-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: turbolinks
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: font-awesome-sass
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Server-side tooltips for your Ruby on Rails application with Vanila JS
112
+ email:
113
+ - busko.bogdan@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - MIT-LICENSE
119
+ - README.md
120
+ - Rakefile
121
+ - app/assets/javascripts/awesome_tooltip/tooltip.js
122
+ - app/assets/stylesheets/awesome_tooltip/tooltip.scss
123
+ - app/controllers/awesome_tooltip/application_controller.rb
124
+ - app/controllers/awesome_tooltip/tooltips_controller.rb
125
+ - config/routes.rb
126
+ - lib/awesome_tooltip.rb
127
+ - lib/awesome_tooltip/engine.rb
128
+ - lib/awesome_tooltip/railtie.rb
129
+ - lib/awesome_tooltip/version.rb
130
+ homepage: https://github.com/BogdanBusko/awesome_tooltip
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubygems_version: 3.0.6
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: Server-side tooltips for your Ruby on Rails application with Vanila JS
153
+ test_files: []