machinery-tool 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/COPYING +674 -0
- data/NEWS +143 -0
- data/bin/machinery +29 -0
- data/helpers/changed_managed_files.sh +32 -0
- data/helpers/filter-packages-for-build.yaml +6 -0
- data/html/assets/arrow_down.png +0 -0
- data/html/assets/arrow_up.png +0 -0
- data/html/assets/bootstrap-popover.js +113 -0
- data/html/assets/bootstrap-tooltip.js +457 -0
- data/html/assets/bootstrap.min.css +5 -0
- data/html/assets/collapse.js +174 -0
- data/html/assets/hogan-3.0.2.min.mustache.js +5 -0
- data/html/assets/jquery-2.1.1.min.js +4 -0
- data/html/assets/logo-changed-managed-files-small.png +0 -0
- data/html/assets/logo-changed-managed-files.png +0 -0
- data/html/assets/logo-config-files-small.png +0 -0
- data/html/assets/logo-config-files.png +0 -0
- data/html/assets/logo-groups-small.png +0 -0
- data/html/assets/logo-groups.png +0 -0
- data/html/assets/logo-os-small.png +0 -0
- data/html/assets/logo-os.png +0 -0
- data/html/assets/logo-packages-small.png +0 -0
- data/html/assets/logo-packages.png +0 -0
- data/html/assets/logo-patterns-small.png +0 -0
- data/html/assets/logo-patterns.png +0 -0
- data/html/assets/logo-repositories-small.png +0 -0
- data/html/assets/logo-repositories.png +0 -0
- data/html/assets/logo-services-small.png +0 -0
- data/html/assets/logo-services.png +0 -0
- data/html/assets/logo-unmanaged-files-small.png +0 -0
- data/html/assets/logo-unmanaged-files.png +0 -0
- data/html/assets/logo-users-small.png +0 -0
- data/html/assets/logo-users.png +0 -0
- data/html/assets/machinery-base.css +5767 -0
- data/html/assets/machinery.css +131 -0
- data/html/assets/machinery.js +148 -0
- data/html/assets/transition.js +59 -0
- data/html/assets/wheels_horizontal.png +0 -0
- data/html/index.html.haml +468 -0
- data/kiwi_helpers/kiwi_export_readme.md +22 -0
- data/kiwi_helpers/merge_users_and_groups.pl.erb +231 -0
- data/kiwi_helpers/unmanaged_files_build_excludes +5 -0
- data/lib/analyze_config_file_diffs_task.rb +130 -0
- data/lib/array.rb +98 -0
- data/lib/build_task.rb +124 -0
- data/lib/changed_rpm_files_helper.rb +96 -0
- data/lib/cli.rb +600 -0
- data/lib/compare_task.rb +68 -0
- data/lib/config.rb +33 -0
- data/lib/config_base.rb +117 -0
- data/lib/config_task.rb +56 -0
- data/lib/constants.rb +24 -0
- data/lib/copy_task.rb +22 -0
- data/lib/current_user.rb +23 -0
- data/lib/deploy_task.rb +89 -0
- data/lib/exceptions.rb +113 -0
- data/lib/generate_html_task.rb +22 -0
- data/lib/helper.rb +22 -0
- data/lib/hint.rb +39 -0
- data/lib/html.rb +103 -0
- data/lib/inspect_task.rb +93 -0
- data/lib/inspector.rb +65 -0
- data/lib/kiwi_config.rb +356 -0
- data/lib/kiwi_export_task.rb +36 -0
- data/lib/list_task.rb +64 -0
- data/lib/local_system.rb +127 -0
- data/lib/logged_cheetah.rb +25 -0
- data/lib/machinery.rb +85 -0
- data/lib/machinery_logger.rb +47 -0
- data/lib/migration.rb +128 -0
- data/lib/mountpoints.rb +72 -0
- data/lib/object.rb +138 -0
- data/lib/os.rb +78 -0
- data/lib/remote_system.rb +114 -0
- data/lib/remove_task.rb +43 -0
- data/lib/renderer.rb +243 -0
- data/lib/renderer_helper.rb +26 -0
- data/lib/rpm.rb +52 -0
- data/lib/scope_mixin.rb +38 -0
- data/lib/show_task.rb +65 -0
- data/lib/system.rb +81 -0
- data/lib/system_description.rb +228 -0
- data/lib/system_description_store.rb +167 -0
- data/lib/system_description_validator.rb +216 -0
- data/lib/tarball.rb +82 -0
- data/lib/ui.rb +74 -0
- data/lib/upgrade_format_task.rb +55 -0
- data/lib/validate_task.rb +23 -0
- data/lib/version.rb +22 -0
- data/lib/zypper.rb +70 -0
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +1056 -0
- data/plugins/docs/changed_managed_files.md +2 -0
- data/plugins/docs/config_files.md +5 -0
- data/plugins/docs/groups.md +2 -0
- data/plugins/docs/os.md +2 -0
- data/plugins/docs/packages.md +2 -0
- data/plugins/docs/patterns.md +5 -0
- data/plugins/docs/repositories.md +24 -0
- data/plugins/docs/services.md +6 -0
- data/plugins/docs/unmanaged_files.md +13 -0
- data/plugins/docs/users.md +3 -0
- data/plugins/inspect/changed_managed_files_inspector.rb +109 -0
- data/plugins/inspect/config_files_inspector.rb +117 -0
- data/plugins/inspect/groups_inspector.rb +46 -0
- data/plugins/inspect/os_inspector.rb +116 -0
- data/plugins/inspect/packages_inspector.rb +46 -0
- data/plugins/inspect/patterns_inspector.rb +67 -0
- data/plugins/inspect/repositories_inspector.rb +107 -0
- data/plugins/inspect/services_inspector.rb +88 -0
- data/plugins/inspect/unmanaged_files_inspector.rb +393 -0
- data/plugins/inspect/users_inspector.rb +87 -0
- data/plugins/model/changed_managed_files_model.rb +29 -0
- data/plugins/model/config_files_model.rb +29 -0
- data/plugins/model/groups_model.rb +26 -0
- data/plugins/model/os_model.rb +20 -0
- data/plugins/model/packages_model.rb +26 -0
- data/plugins/model/patterns_model.rb +26 -0
- data/plugins/model/repositories_model.rb +26 -0
- data/plugins/model/services_model.rb +48 -0
- data/plugins/model/unmanaged_files_model.rb +29 -0
- data/plugins/model/users_model.rb +26 -0
- data/plugins/schema/v1/system-description-changed-managed-files.schema.json +83 -0
- data/plugins/schema/v1/system-description-config-files.schema.json +83 -0
- data/plugins/schema/v1/system-description-groups.schema.json +30 -0
- data/plugins/schema/v1/system-description-os.schema.json +21 -0
- data/plugins/schema/v1/system-description-packages.schema.json +34 -0
- data/plugins/schema/v1/system-description-patterns.schema.json +24 -0
- data/plugins/schema/v1/system-description-repositories.schema.json +41 -0
- data/plugins/schema/v1/system-description-services.schema.json +30 -0
- data/plugins/schema/v1/system-description-unmanaged-files.schema.json +105 -0
- data/plugins/schema/v1/system-description-users.schema.json +61 -0
- data/plugins/schema/v2/system-description-changed-managed-files.schema.json +92 -0
- data/plugins/schema/v2/system-description-config-files.schema.json +92 -0
- data/plugins/schema/v2/system-description-groups.schema.json +30 -0
- data/plugins/schema/v2/system-description-os.schema.json +21 -0
- data/plugins/schema/v2/system-description-packages.schema.json +34 -0
- data/plugins/schema/v2/system-description-patterns.schema.json +24 -0
- data/plugins/schema/v2/system-description-repositories.schema.json +41 -0
- data/plugins/schema/v2/system-description-services.schema.json +30 -0
- data/plugins/schema/v2/system-description-unmanaged-files.schema.json +138 -0
- data/plugins/schema/v2/system-description-users.schema.json +61 -0
- data/plugins/show/changed_managed_files_renderer.rb +46 -0
- data/plugins/show/config_files_renderer.rb +62 -0
- data/plugins/show/groups_renderer.rb +36 -0
- data/plugins/show/os_renderer.rb +31 -0
- data/plugins/show/packages_renderer.rb +32 -0
- data/plugins/show/patterns_renderer.rb +32 -0
- data/plugins/show/repositories_renderer.rb +38 -0
- data/plugins/show/services_renderer.rb +32 -0
- data/plugins/show/unmanaged_files_renderer.rb +42 -0
- data/plugins/show/users_renderer.rb +35 -0
- data/schema/migrations/migrate1to2.rb +56 -0
- data/schema/v1/system-description-global.schema.json +31 -0
- data/schema/v2/system-description-global.schema.json +31 -0
- metadata +370 -0
data/NEWS
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Machinery Release Notes
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## Version 1.0.1 - Tue Oct 28 16:24:16 CET 2014 - thardeck@suse.de
|
|
5
|
+
|
|
6
|
+
* Added autofs to the remote file system filter
|
|
7
|
+
|
|
8
|
+
## Version 1.0.0 - Tue Oct 14 12:41:35 CEST 2014 - thardeck@suse.de
|
|
9
|
+
|
|
10
|
+
* SLES12 release version
|
|
11
|
+
|
|
12
|
+
## Version 0.21.0 - Tue Oct 14 12:07:33 CEST 2014 - thardeck@suse.de
|
|
13
|
+
|
|
14
|
+
* Added HTML view of system descriptions
|
|
15
|
+
* Add format version to `machinery --version` output
|
|
16
|
+
* Added work flow hints to make machinery easier approchable
|
|
17
|
+
* Improve validation to also check the existence of extracted files
|
|
18
|
+
* Added filtering of remote mount points during unmanaged-files inspection
|
|
19
|
+
* Increased format version to 2
|
|
20
|
+
|
|
21
|
+
## Version 0.20.0 - Tue Sep 09 14:43:15 CEST 2014 - thardeck@suse.de
|
|
22
|
+
|
|
23
|
+
* Processed descriptions are validated against a set of JSON schemas
|
|
24
|
+
* File structure of processed descriptions is validated
|
|
25
|
+
* System descriptions can also be validated manually with the command `validate`
|
|
26
|
+
* Enhanced package inspector to also inspect package architecture, checksum and revision
|
|
27
|
+
|
|
28
|
+
## Version 0.19.0 - Mon Aug 18 17:55:51 CEST 2014 - thardeck@suse.de
|
|
29
|
+
|
|
30
|
+
* Introduced system description versioning. This change prevents usage of old system descriptions.
|
|
31
|
+
* Fixed issue #59 by filtering invalid UTF-8 characters during inspection
|
|
32
|
+
* Added support for building openSUSE 13.1 images
|
|
33
|
+
* Formatted list output to be more readable
|
|
34
|
+
|
|
35
|
+
## Version 0.18.0 - Wed Aug 06 18:37:26 CEST 2014 - thardeck@suse.de
|
|
36
|
+
|
|
37
|
+
* Fixed bnc#888786 - fix analyzing of config files with restricted repositories
|
|
38
|
+
* Fixed bnc#879990 - check if building is supported on the current platform
|
|
39
|
+
* Added distinction between expected and unexpected errors
|
|
40
|
+
* Prevented truncated error messages
|
|
41
|
+
* Renamed `clone` command to `copy`
|
|
42
|
+
|
|
43
|
+
## Version 0.17.2 - Thu Jul 17 11:32:43 CEST 2014 - thardeck@suse.de
|
|
44
|
+
|
|
45
|
+
* Removed incomplete bash completion support
|
|
46
|
+
|
|
47
|
+
## Version 0.17.1 - Tue Jul 15 13:29:15 CEST 2014 - thardeck@suse.de
|
|
48
|
+
|
|
49
|
+
* Fixed bnc#883028 - check for Kiwi dependencies
|
|
50
|
+
* Fixed inspection of systems without repositories
|
|
51
|
+
* Fixed misleading help descriptions
|
|
52
|
+
|
|
53
|
+
## Version 0.17.0 - Tue Jul 01 13:16:10 CEST 2014 - thardeck@suse.de
|
|
54
|
+
|
|
55
|
+
* Added bash completion support
|
|
56
|
+
* Kiwi export now includes a how-to
|
|
57
|
+
* Added the option "--exclude-scope" to allow omission of scopes
|
|
58
|
+
|
|
59
|
+
## Version 0.16.0 - Mon Jun 16 15:08:24 CEST 2014 - thardeck@suse.de
|
|
60
|
+
|
|
61
|
+
* Adapted the diff format according to user feedback
|
|
62
|
+
* Added `clone` command to copy system descriptions
|
|
63
|
+
|
|
64
|
+
## Version 0.15.0 - Mon Jun 02 14:20:58 CEST 2014 - thardeck@suse.de
|
|
65
|
+
|
|
66
|
+
* Added `analyze` command with the option "--operation=config-file-diffs" to generate the diff of changed config files by downloading the packages. The diff can be shown by running `show` with the option "--show-diffs"
|
|
67
|
+
* Added `compare` command to see the differences between two systems descriptions
|
|
68
|
+
|
|
69
|
+
## Version 0.14.0 - Mon May 19 18:18:48 CEST 2014 - thardeck@suse.de
|
|
70
|
+
|
|
71
|
+
* Added support for building SLES 12 images
|
|
72
|
+
* Optimized extraction of unmanaged files from SLES 12 systems
|
|
73
|
+
* The scope command line option now accepts abbreviated scope names
|
|
74
|
+
|
|
75
|
+
## Version 0.13.0 - Tue May 06 13:49:51 CEST 2014 - thardeck@suse.de
|
|
76
|
+
|
|
77
|
+
* Added inspection for systemd services
|
|
78
|
+
* Added deployment of build images to OpenStack cloud
|
|
79
|
+
|
|
80
|
+
## Version 0.12.0 - Tue Apr 29 10:21:41 CEST 2014 - thardeck@suse.de
|
|
81
|
+
|
|
82
|
+
* Added inspection of users
|
|
83
|
+
* Added inspection of groups
|
|
84
|
+
|
|
85
|
+
## Version 0.11.0 - Tue Apr 22 13:00:43 CEST 2014 - thardeck@suse.de
|
|
86
|
+
|
|
87
|
+
* Inspector for repository credentials implemented
|
|
88
|
+
* Added command to export SLE11 system descriptions as Kiwi image descriptions
|
|
89
|
+
|
|
90
|
+
## Version 0.10.3 - Tue Apr 08 12:50:32 CEST 2014 - thardeck@suse.de
|
|
91
|
+
|
|
92
|
+
* Added SLES 12 support for the inspector services
|
|
93
|
+
|
|
94
|
+
## Version 0.10.1 - Mon Apr 07 12:46:21 CEST 2014 - thardeck@suse.de
|
|
95
|
+
|
|
96
|
+
* Added SLES 12 support for the inspector patterns
|
|
97
|
+
|
|
98
|
+
## Version 0.10.0 - Mon Apr 07 09:00:21 CEST 2014 - thardeck@suse.de
|
|
99
|
+
|
|
100
|
+
* Made Machinery run on SLES12
|
|
101
|
+
* Added SLES 12 support for the inspectors packages, repositories, os, config-files, changed-managed-files and unmanaged-files
|
|
102
|
+
|
|
103
|
+
## Version 0.9.0 - Mon Mar 24 17:56:13 CET 2014 - thardeck@suse.de
|
|
104
|
+
|
|
105
|
+
* Inspector for changed managed files implemented
|
|
106
|
+
* Extraction of unmanaged-files meta data implemented
|
|
107
|
+
* Graceful handling of inspection errors
|
|
108
|
+
|
|
109
|
+
## Version 0.8.0 - Tue Mar 11 12:11:46 CET 2014 - thardeck@suse.de
|
|
110
|
+
|
|
111
|
+
* Added logging
|
|
112
|
+
* Inspector for unmanaged-files implemented
|
|
113
|
+
* Extraction of unmanaged-files implemented
|
|
114
|
+
|
|
115
|
+
## Version 0.7.0 - Mon Feb 24 16:21:51 CET 2014 - thardeck@suse.de
|
|
116
|
+
|
|
117
|
+
* Inspector for the operating system and version implemented
|
|
118
|
+
* Inspector for installed services implemented
|
|
119
|
+
* Timestamps are now shown with each scope
|
|
120
|
+
|
|
121
|
+
## Version 0.6.0 - Mon Feb 10 17:20:04 CET 2014 - thardeck@suse.de
|
|
122
|
+
|
|
123
|
+
* Inspected config-files can now be included in the build image
|
|
124
|
+
* Improved documentation of the scopes
|
|
125
|
+
* Added merging of system description scopes for each system
|
|
126
|
+
* Added summary output for inspection results
|
|
127
|
+
* Added show command to output the system description data
|
|
128
|
+
* Added list command to list system descriptions
|
|
129
|
+
* Added clean command to remove system descriptions
|
|
130
|
+
|
|
131
|
+
## Version 0.5.0 - Mon Jan 27 14:53:29 CET 2014 - thardeck@suse.de
|
|
132
|
+
|
|
133
|
+
* Added command to build SLES11SP3 qcow2 images based on inspected repositories and packages
|
|
134
|
+
|
|
135
|
+
## Version 0.4.0 - Mon Jan 13 18:14:40 CET 2014 - thardeck@suse.de
|
|
136
|
+
|
|
137
|
+
* Inspector for changed configuration files implemented
|
|
138
|
+
* Inspector for patterns implemented
|
|
139
|
+
|
|
140
|
+
## Version 0.1.0 - Tue Dec 17 14:06:59 CET 2013 - aduffeck@suse.de
|
|
141
|
+
|
|
142
|
+
* Package and repository inspection of SLES 11 systems
|
|
143
|
+
|
data/bin/machinery
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
4
|
+
#
|
|
5
|
+
# This program is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
7
|
+
# published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, contact SUSE LLC.
|
|
16
|
+
#
|
|
17
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
18
|
+
# you may find current contact information at www.suse.com
|
|
19
|
+
|
|
20
|
+
require_relative '../lib/machinery'
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
LocalSystem.validate_machinery_compatibility
|
|
24
|
+
Machinery.initialize_logger(ENV["MACHINERY_LOG_FILE"] || Machinery::DEFAULT_LOG_FILE)
|
|
25
|
+
Machinery.logger.info "Executing '#{$0} #{ARGV.join(" ")}'"
|
|
26
|
+
Cli.run(ARGV)
|
|
27
|
+
rescue Machinery::Errors::IncompatibleHost => e
|
|
28
|
+
puts e
|
|
29
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
3
|
+
#
|
|
4
|
+
# This program is free software; you can redistribute it and/or
|
|
5
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
6
|
+
# published by the Free Software Foundation.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program; if not, contact SUSE LLC.
|
|
15
|
+
#
|
|
16
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
17
|
+
# you may find current contact information at www.suse.com
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Print a list of each package with changed managed files followed by a list of
|
|
21
|
+
# the changed files, e.g.
|
|
22
|
+
#
|
|
23
|
+
# libpulse0-4.0.git.270.g9490a:
|
|
24
|
+
# S.5...... c /etc/pulse/client.conf
|
|
25
|
+
# ntp-4.2.6p5:
|
|
26
|
+
# S.5...... c /etc/ntp.conf
|
|
27
|
+
for package in `rpm -qa --queryformat "%{NAME}-%{VERSION}\\n"`; do
|
|
28
|
+
CHANGES=`rpm -V --nodeps --nodigest --nosignature --nomtime --nolinkto $package`;
|
|
29
|
+
if [ -n "$CHANGES" ]; then
|
|
30
|
+
echo -e "$package:\\n$CHANGES";
|
|
31
|
+
fi;
|
|
32
|
+
done
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* ========================================================================
|
|
2
|
+
* Bootstrap: popover.js v3.2.0
|
|
3
|
+
* http://getbootstrap.com/javascript/#popovers
|
|
4
|
+
* ========================================================================
|
|
5
|
+
* Copyright 2011-2014 Twitter, Inc.
|
|
6
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
7
|
+
* ======================================================================== */
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
+function ($) {
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
// POPOVER PUBLIC CLASS DEFINITION
|
|
14
|
+
// ===============================
|
|
15
|
+
|
|
16
|
+
var Popover = function (element, options) {
|
|
17
|
+
this.init('popover', element, options)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
|
|
21
|
+
|
|
22
|
+
Popover.VERSION = '3.2.0'
|
|
23
|
+
|
|
24
|
+
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
|
|
25
|
+
placement: 'right',
|
|
26
|
+
trigger: 'click',
|
|
27
|
+
content: '',
|
|
28
|
+
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// NOTE: POPOVER EXTENDS tooltip.js
|
|
33
|
+
// ================================
|
|
34
|
+
|
|
35
|
+
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
|
|
36
|
+
|
|
37
|
+
Popover.prototype.constructor = Popover
|
|
38
|
+
|
|
39
|
+
Popover.prototype.getDefaults = function () {
|
|
40
|
+
return Popover.DEFAULTS
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Popover.prototype.setContent = function () {
|
|
44
|
+
var $tip = this.tip()
|
|
45
|
+
var title = this.getTitle()
|
|
46
|
+
var content = this.getContent()
|
|
47
|
+
|
|
48
|
+
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
|
|
49
|
+
$tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
|
|
50
|
+
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
|
|
51
|
+
](content)
|
|
52
|
+
|
|
53
|
+
$tip.removeClass('fade top bottom left right in')
|
|
54
|
+
|
|
55
|
+
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
|
|
56
|
+
// this manually by checking the contents.
|
|
57
|
+
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Popover.prototype.hasContent = function () {
|
|
61
|
+
return this.getTitle() || this.getContent()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Popover.prototype.getContent = function () {
|
|
65
|
+
var $e = this.$element
|
|
66
|
+
var o = this.options
|
|
67
|
+
|
|
68
|
+
return $e.attr('data-content')
|
|
69
|
+
|| (typeof o.content == 'function' ?
|
|
70
|
+
o.content.call($e[0]) :
|
|
71
|
+
o.content)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
Popover.prototype.arrow = function () {
|
|
75
|
+
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
Popover.prototype.tip = function () {
|
|
79
|
+
if (!this.$tip) this.$tip = $(this.options.template)
|
|
80
|
+
return this.$tip
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// POPOVER PLUGIN DEFINITION
|
|
85
|
+
// =========================
|
|
86
|
+
|
|
87
|
+
function Plugin(option) {
|
|
88
|
+
return this.each(function () {
|
|
89
|
+
var $this = $(this)
|
|
90
|
+
var data = $this.data('bs.popover')
|
|
91
|
+
var options = typeof option == 'object' && option
|
|
92
|
+
|
|
93
|
+
if (!data && option == 'destroy') return
|
|
94
|
+
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
|
|
95
|
+
if (typeof option == 'string') data[option]()
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
var old = $.fn.popover
|
|
100
|
+
|
|
101
|
+
$.fn.popover = Plugin
|
|
102
|
+
$.fn.popover.Constructor = Popover
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
// POPOVER NO CONFLICT
|
|
106
|
+
// ===================
|
|
107
|
+
|
|
108
|
+
$.fn.popover.noConflict = function () {
|
|
109
|
+
$.fn.popover = old
|
|
110
|
+
return this
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}(jQuery);
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/* ========================================================================
|
|
2
|
+
* Bootstrap: tooltip.js v3.2.0
|
|
3
|
+
* http://getbootstrap.com/javascript/#tooltip
|
|
4
|
+
* Inspired by the original jQuery.tipsy by Jason Frame
|
|
5
|
+
* ========================================================================
|
|
6
|
+
* Copyright 2011-2014 Twitter, Inc.
|
|
7
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
8
|
+
* ======================================================================== */
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
+function ($) {
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
// TOOLTIP PUBLIC CLASS DEFINITION
|
|
15
|
+
// ===============================
|
|
16
|
+
|
|
17
|
+
var Tooltip = function (element, options) {
|
|
18
|
+
this.type =
|
|
19
|
+
this.options =
|
|
20
|
+
this.enabled =
|
|
21
|
+
this.timeout =
|
|
22
|
+
this.hoverState =
|
|
23
|
+
this.$element = null
|
|
24
|
+
|
|
25
|
+
this.init('tooltip', element, options)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Tooltip.VERSION = '3.2.0'
|
|
29
|
+
|
|
30
|
+
Tooltip.DEFAULTS = {
|
|
31
|
+
animation: true,
|
|
32
|
+
placement: 'top',
|
|
33
|
+
selector: false,
|
|
34
|
+
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
|
|
35
|
+
trigger: 'hover focus',
|
|
36
|
+
title: '',
|
|
37
|
+
delay: 0,
|
|
38
|
+
html: false,
|
|
39
|
+
container: false,
|
|
40
|
+
viewport: {
|
|
41
|
+
selector: 'body',
|
|
42
|
+
padding: 0
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Tooltip.prototype.init = function (type, element, options) {
|
|
47
|
+
this.enabled = true
|
|
48
|
+
this.type = type
|
|
49
|
+
this.$element = $(element)
|
|
50
|
+
this.options = this.getOptions(options)
|
|
51
|
+
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
|
|
52
|
+
|
|
53
|
+
var triggers = this.options.trigger.split(' ')
|
|
54
|
+
|
|
55
|
+
for (var i = triggers.length; i--;) {
|
|
56
|
+
var trigger = triggers[i]
|
|
57
|
+
|
|
58
|
+
if (trigger == 'click') {
|
|
59
|
+
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
|
60
|
+
} else if (trigger != 'manual') {
|
|
61
|
+
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
|
|
62
|
+
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
|
|
63
|
+
|
|
64
|
+
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
|
65
|
+
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.options.selector ?
|
|
70
|
+
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
|
71
|
+
this.fixTitle()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
Tooltip.prototype.getDefaults = function () {
|
|
75
|
+
return Tooltip.DEFAULTS
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
Tooltip.prototype.getOptions = function (options) {
|
|
79
|
+
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
|
|
80
|
+
|
|
81
|
+
if (options.delay && typeof options.delay == 'number') {
|
|
82
|
+
options.delay = {
|
|
83
|
+
show: options.delay,
|
|
84
|
+
hide: options.delay
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return options
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
Tooltip.prototype.getDelegateOptions = function () {
|
|
92
|
+
var options = {}
|
|
93
|
+
var defaults = this.getDefaults()
|
|
94
|
+
|
|
95
|
+
this._options && $.each(this._options, function (key, value) {
|
|
96
|
+
if (defaults[key] != value) options[key] = value
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return options
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
Tooltip.prototype.enter = function (obj) {
|
|
103
|
+
var self = obj instanceof this.constructor ?
|
|
104
|
+
obj : $(obj.currentTarget).data('bs.' + this.type)
|
|
105
|
+
|
|
106
|
+
if (!self) {
|
|
107
|
+
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
|
108
|
+
$(obj.currentTarget).data('bs.' + this.type, self)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
clearTimeout(self.timeout)
|
|
112
|
+
|
|
113
|
+
self.hoverState = 'in'
|
|
114
|
+
|
|
115
|
+
if (!self.options.delay || !self.options.delay.show) return self.show()
|
|
116
|
+
|
|
117
|
+
self.timeout = setTimeout(function () {
|
|
118
|
+
if (self.hoverState == 'in') self.show()
|
|
119
|
+
}, self.options.delay.show)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
Tooltip.prototype.leave = function (obj) {
|
|
123
|
+
var self = obj instanceof this.constructor ?
|
|
124
|
+
obj : $(obj.currentTarget).data('bs.' + this.type)
|
|
125
|
+
|
|
126
|
+
if (!self) {
|
|
127
|
+
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
|
128
|
+
$(obj.currentTarget).data('bs.' + this.type, self)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
clearTimeout(self.timeout)
|
|
132
|
+
|
|
133
|
+
self.hoverState = 'out'
|
|
134
|
+
|
|
135
|
+
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
|
136
|
+
|
|
137
|
+
self.timeout = setTimeout(function () {
|
|
138
|
+
if (self.hoverState == 'out') self.hide()
|
|
139
|
+
}, self.options.delay.hide)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Tooltip.prototype.show = function () {
|
|
143
|
+
var e = $.Event('show.bs.' + this.type)
|
|
144
|
+
|
|
145
|
+
if (this.hasContent() && this.enabled) {
|
|
146
|
+
this.$element.trigger(e)
|
|
147
|
+
|
|
148
|
+
var inDom = $.contains(document.documentElement, this.$element[0])
|
|
149
|
+
if (e.isDefaultPrevented() || !inDom) return
|
|
150
|
+
var that = this
|
|
151
|
+
|
|
152
|
+
var $tip = this.tip()
|
|
153
|
+
|
|
154
|
+
var tipId = this.getUID(this.type)
|
|
155
|
+
|
|
156
|
+
this.setContent()
|
|
157
|
+
$tip.attr('id', tipId)
|
|
158
|
+
this.$element.attr('aria-describedby', tipId)
|
|
159
|
+
|
|
160
|
+
if (this.options.animation) $tip.addClass('fade')
|
|
161
|
+
|
|
162
|
+
var placement = typeof this.options.placement == 'function' ?
|
|
163
|
+
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
|
164
|
+
this.options.placement
|
|
165
|
+
|
|
166
|
+
var autoToken = /\s?auto?\s?/i
|
|
167
|
+
var autoPlace = autoToken.test(placement)
|
|
168
|
+
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
|
|
169
|
+
|
|
170
|
+
$tip
|
|
171
|
+
.detach()
|
|
172
|
+
.css({ top: 0, left: 0, display: 'block' })
|
|
173
|
+
.addClass(placement)
|
|
174
|
+
.data('bs.' + this.type, this)
|
|
175
|
+
|
|
176
|
+
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
|
|
177
|
+
|
|
178
|
+
var pos = this.getPosition()
|
|
179
|
+
var actualWidth = $tip[0].offsetWidth
|
|
180
|
+
var actualHeight = $tip[0].offsetHeight
|
|
181
|
+
|
|
182
|
+
if (autoPlace) {
|
|
183
|
+
var orgPlacement = placement
|
|
184
|
+
var $parent = this.$element.parent()
|
|
185
|
+
var parentDim = this.getPosition($parent)
|
|
186
|
+
|
|
187
|
+
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
|
|
188
|
+
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
|
|
189
|
+
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
|
|
190
|
+
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
|
|
191
|
+
placement
|
|
192
|
+
|
|
193
|
+
$tip
|
|
194
|
+
.removeClass(orgPlacement)
|
|
195
|
+
.addClass(placement)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
|
|
199
|
+
|
|
200
|
+
this.applyPlacement(calculatedOffset, placement)
|
|
201
|
+
|
|
202
|
+
var complete = function () {
|
|
203
|
+
that.$element.trigger('shown.bs.' + that.type)
|
|
204
|
+
that.hoverState = null
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
$.support.transition && this.$tip.hasClass('fade') ?
|
|
208
|
+
$tip
|
|
209
|
+
.one('bsTransitionEnd', complete)
|
|
210
|
+
.emulateTransitionEnd(150) :
|
|
211
|
+
complete()
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
Tooltip.prototype.applyPlacement = function (offset, placement) {
|
|
216
|
+
var $tip = this.tip()
|
|
217
|
+
var width = $tip[0].offsetWidth
|
|
218
|
+
var height = $tip[0].offsetHeight
|
|
219
|
+
|
|
220
|
+
// manually read margins because getBoundingClientRect includes difference
|
|
221
|
+
var marginTop = parseInt($tip.css('margin-top'), 10)
|
|
222
|
+
var marginLeft = parseInt($tip.css('margin-left'), 10)
|
|
223
|
+
|
|
224
|
+
// we must check for NaN for ie 8/9
|
|
225
|
+
if (isNaN(marginTop)) marginTop = 0
|
|
226
|
+
if (isNaN(marginLeft)) marginLeft = 0
|
|
227
|
+
|
|
228
|
+
offset.top = offset.top + marginTop
|
|
229
|
+
offset.left = offset.left + marginLeft
|
|
230
|
+
|
|
231
|
+
// $.fn.offset doesn't round pixel values
|
|
232
|
+
// so we use setOffset directly with our own function B-0
|
|
233
|
+
$.offset.setOffset($tip[0], $.extend({
|
|
234
|
+
using: function (props) {
|
|
235
|
+
$tip.css({
|
|
236
|
+
top: Math.round(props.top),
|
|
237
|
+
left: Math.round(props.left)
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
}, offset), 0)
|
|
241
|
+
|
|
242
|
+
$tip.addClass('in')
|
|
243
|
+
|
|
244
|
+
// check to see if placing tip in new offset caused the tip to resize itself
|
|
245
|
+
var actualWidth = $tip[0].offsetWidth
|
|
246
|
+
var actualHeight = $tip[0].offsetHeight
|
|
247
|
+
|
|
248
|
+
if (placement == 'top' && actualHeight != height) {
|
|
249
|
+
offset.top = offset.top + height - actualHeight
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
|
|
253
|
+
|
|
254
|
+
if (delta.left) offset.left += delta.left
|
|
255
|
+
else offset.top += delta.top
|
|
256
|
+
|
|
257
|
+
var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
|
|
258
|
+
var arrowPosition = delta.left ? 'left' : 'top'
|
|
259
|
+
var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
|
|
260
|
+
|
|
261
|
+
$tip.offset(offset)
|
|
262
|
+
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
|
|
266
|
+
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
Tooltip.prototype.setContent = function () {
|
|
270
|
+
var $tip = this.tip()
|
|
271
|
+
var title = this.getTitle()
|
|
272
|
+
|
|
273
|
+
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
|
|
274
|
+
$tip.removeClass('fade in top bottom left right')
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
Tooltip.prototype.hide = function () {
|
|
278
|
+
var that = this
|
|
279
|
+
var $tip = this.tip()
|
|
280
|
+
var e = $.Event('hide.bs.' + this.type)
|
|
281
|
+
|
|
282
|
+
this.$element.removeAttr('aria-describedby')
|
|
283
|
+
|
|
284
|
+
function complete() {
|
|
285
|
+
if (that.hoverState != 'in') $tip.detach()
|
|
286
|
+
that.$element.trigger('hidden.bs.' + that.type)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
this.$element.trigger(e)
|
|
290
|
+
|
|
291
|
+
if (e.isDefaultPrevented()) return
|
|
292
|
+
|
|
293
|
+
$tip.removeClass('in')
|
|
294
|
+
|
|
295
|
+
$.support.transition && this.$tip.hasClass('fade') ?
|
|
296
|
+
$tip
|
|
297
|
+
.one('bsTransitionEnd', complete)
|
|
298
|
+
.emulateTransitionEnd(150) :
|
|
299
|
+
complete()
|
|
300
|
+
|
|
301
|
+
this.hoverState = null
|
|
302
|
+
|
|
303
|
+
return this
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
Tooltip.prototype.fixTitle = function () {
|
|
307
|
+
var $e = this.$element
|
|
308
|
+
if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
|
|
309
|
+
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
Tooltip.prototype.hasContent = function () {
|
|
314
|
+
return this.getTitle()
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
Tooltip.prototype.getPosition = function ($element) {
|
|
318
|
+
$element = $element || this.$element
|
|
319
|
+
var el = $element[0]
|
|
320
|
+
var isBody = el.tagName == 'BODY'
|
|
321
|
+
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
|
|
322
|
+
scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
|
|
323
|
+
width: isBody ? $(window).width() : $element.outerWidth(),
|
|
324
|
+
height: isBody ? $(window).height() : $element.outerHeight()
|
|
325
|
+
}, isBody ? { top: 0, left: 0 } : $element.offset())
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
|
|
329
|
+
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
|
330
|
+
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
|
331
|
+
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
|
|
332
|
+
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
|
|
337
|
+
var delta = { top: 0, left: 0 }
|
|
338
|
+
if (!this.$viewport) return delta
|
|
339
|
+
|
|
340
|
+
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
|
|
341
|
+
var viewportDimensions = this.getPosition(this.$viewport)
|
|
342
|
+
|
|
343
|
+
if (/right|left/.test(placement)) {
|
|
344
|
+
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
|
|
345
|
+
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
|
|
346
|
+
if (topEdgeOffset < viewportDimensions.top) { // top overflow
|
|
347
|
+
delta.top = viewportDimensions.top - topEdgeOffset
|
|
348
|
+
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
|
|
349
|
+
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
var leftEdgeOffset = pos.left - viewportPadding
|
|
353
|
+
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
|
|
354
|
+
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
|
|
355
|
+
delta.left = viewportDimensions.left - leftEdgeOffset
|
|
356
|
+
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
|
|
357
|
+
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return delta
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
Tooltip.prototype.getTitle = function () {
|
|
365
|
+
var title
|
|
366
|
+
var $e = this.$element
|
|
367
|
+
var o = this.options
|
|
368
|
+
|
|
369
|
+
title = $e.attr('data-original-title')
|
|
370
|
+
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
|
371
|
+
|
|
372
|
+
return title
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
Tooltip.prototype.getUID = function (prefix) {
|
|
376
|
+
do prefix += ~~(Math.random() * 1000000)
|
|
377
|
+
while (document.getElementById(prefix))
|
|
378
|
+
return prefix
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
Tooltip.prototype.tip = function () {
|
|
382
|
+
return (this.$tip = this.$tip || $(this.options.template))
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
Tooltip.prototype.arrow = function () {
|
|
386
|
+
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
Tooltip.prototype.validate = function () {
|
|
390
|
+
if (!this.$element[0].parentNode) {
|
|
391
|
+
this.hide()
|
|
392
|
+
this.$element = null
|
|
393
|
+
this.options = null
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
Tooltip.prototype.enable = function () {
|
|
398
|
+
this.enabled = true
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
Tooltip.prototype.disable = function () {
|
|
402
|
+
this.enabled = false
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
Tooltip.prototype.toggleEnabled = function () {
|
|
406
|
+
this.enabled = !this.enabled
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
Tooltip.prototype.toggle = function (e) {
|
|
410
|
+
var self = this
|
|
411
|
+
if (e) {
|
|
412
|
+
self = $(e.currentTarget).data('bs.' + this.type)
|
|
413
|
+
if (!self) {
|
|
414
|
+
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
|
|
415
|
+
$(e.currentTarget).data('bs.' + this.type, self)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
Tooltip.prototype.destroy = function () {
|
|
423
|
+
clearTimeout(this.timeout)
|
|
424
|
+
this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
// TOOLTIP PLUGIN DEFINITION
|
|
429
|
+
// =========================
|
|
430
|
+
|
|
431
|
+
function Plugin(option) {
|
|
432
|
+
return this.each(function () {
|
|
433
|
+
var $this = $(this)
|
|
434
|
+
var data = $this.data('bs.tooltip')
|
|
435
|
+
var options = typeof option == 'object' && option
|
|
436
|
+
|
|
437
|
+
if (!data && option == 'destroy') return
|
|
438
|
+
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
|
|
439
|
+
if (typeof option == 'string') data[option]()
|
|
440
|
+
})
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
var old = $.fn.tooltip
|
|
444
|
+
|
|
445
|
+
$.fn.tooltip = Plugin
|
|
446
|
+
$.fn.tooltip.Constructor = Tooltip
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
// TOOLTIP NO CONFLICT
|
|
450
|
+
// ===================
|
|
451
|
+
|
|
452
|
+
$.fn.tooltip.noConflict = function () {
|
|
453
|
+
$.fn.tooltip = old
|
|
454
|
+
return this
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
}(jQuery);
|