sharkey-web 3.3.1
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/.gitignore +24 -0
- data/Gemfile +4 -0
- data/LICENSE.md +19 -0
- data/README.md +188 -0
- data/Rakefile +8 -0
- data/bin/sharkey-web +9 -0
- data/config.ru +3 -0
- data/lib/sharkey.rb +12 -0
- data/lib/sharkey/app.rb +526 -0
- data/lib/sharkey/importerexporter.rb +79 -0
- data/lib/sharkey/models.rb +295 -0
- data/lib/sharkey/public/css/loading.gif +0 -0
- data/lib/sharkey/public/css/magicsuggest.css +232 -0
- data/lib/sharkey/public/css/nprogress.css +74 -0
- data/lib/sharkey/public/css/styles.css +263 -0
- data/lib/sharkey/public/css/ui.fancytree.css +545 -0
- data/lib/sharkey/public/data/sentences.txt +5 -0
- data/lib/sharkey/public/fonts/Quadrata.eot +0 -0
- data/lib/sharkey/public/fonts/Quadrata.svg +613 -0
- data/lib/sharkey/public/fonts/Quadrata.ttf +0 -0
- data/lib/sharkey/public/fonts/Quadrata.woff +0 -0
- data/lib/sharkey/public/fonts/Quadrata.zip +0 -0
- data/lib/sharkey/public/images/loader.gif +0 -0
- data/lib/sharkey/public/images/sharkey-logo.png +0 -0
- data/lib/sharkey/public/images/sharkey.png +0 -0
- data/lib/sharkey/public/js/ajaxmanager.js +67 -0
- data/lib/sharkey/public/js/keybindings.js +92 -0
- data/lib/sharkey/public/js/lib/bootstrap.min.js +6 -0
- data/lib/sharkey/public/js/lib/jquery-1.9.1.min.js +5 -0
- data/lib/sharkey/public/js/lib/jquery-ui.js +16150 -0
- data/lib/sharkey/public/js/lib/jquery.bootstrap-autohidingnavbar.js +213 -0
- data/lib/sharkey/public/js/lib/jquery.fancytree-all.js +6424 -0
- data/lib/sharkey/public/js/lib/jquery.tagcloud.js +92 -0
- data/lib/sharkey/public/js/lib/magicsuggest.js +1468 -0
- data/lib/sharkey/public/js/lib/mousetrap.min.js +9 -0
- data/lib/sharkey/public/js/lib/nprogress.js +476 -0
- data/lib/sharkey/public/js/page-add-link-autofill.js +102 -0
- data/lib/sharkey/public/js/page-add-link.js +156 -0
- data/lib/sharkey/public/js/page-categories.js +348 -0
- data/lib/sharkey/public/js/page-edit-link.js +103 -0
- data/lib/sharkey/public/js/page-links.js +54 -0
- data/lib/sharkey/public/js/page-settings.js +93 -0
- data/lib/sharkey/public/js/page-tagcloud.js +35 -0
- data/lib/sharkey/public/js/page-tags.js +287 -0
- data/lib/sharkey/public/js/scripts.js +147 -0
- data/lib/sharkey/public/themes/amelia/style.css +7 -0
- data/lib/sharkey/public/themes/bootstrap/style.css +5785 -0
- data/lib/sharkey/public/themes/cerulean/style.css +7 -0
- data/lib/sharkey/public/themes/cosmo/style.css +7 -0
- data/lib/sharkey/public/themes/cyborg/style.css +7 -0
- data/lib/sharkey/public/themes/darkly/style.css +7 -0
- data/lib/sharkey/public/themes/facebook-like/README.md +6 -0
- data/lib/sharkey/public/themes/facebook-like/style.css +6085 -0
- data/lib/sharkey/public/themes/flatly/style.css +7 -0
- data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/sharkey/public/themes/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/sharkey/public/themes/holo-like/README.md +5 -0
- data/lib/sharkey/public/themes/holo-like/style.css +5997 -0
- data/lib/sharkey/public/themes/journal/style.css +7 -0
- data/lib/sharkey/public/themes/lumen/style.css +7 -0
- data/lib/sharkey/public/themes/readable/style.css +7 -0
- data/lib/sharkey/public/themes/simplex/style.css +7 -0
- data/lib/sharkey/public/themes/slate/style.css +7 -0
- data/lib/sharkey/public/themes/spacelab/style.css +7 -0
- data/lib/sharkey/public/themes/superhero/style.css +7 -0
- data/lib/sharkey/public/themes/united/style.css +7 -0
- data/lib/sharkey/public/themes/yeti/style.css +7 -0
- data/lib/sharkey/setting.rb +74 -0
- data/lib/sharkey/version.rb +5 -0
- data/lib/sharkey/views/404.slim +4 -0
- data/lib/sharkey/views/about.slim +7 -0
- data/lib/sharkey/views/add_link.slim +157 -0
- data/lib/sharkey/views/categories.slim +101 -0
- data/lib/sharkey/views/category.slim +22 -0
- data/lib/sharkey/views/centered.slim +49 -0
- data/lib/sharkey/views/dashboard.slim +107 -0
- data/lib/sharkey/views/dashboard_index.slim +26 -0
- data/lib/sharkey/views/edit_link.slim +121 -0
- data/lib/sharkey/views/help.slim +74 -0
- data/lib/sharkey/views/keybindings.slim +58 -0
- data/lib/sharkey/views/link.slim +30 -0
- data/lib/sharkey/views/links.slim +22 -0
- data/lib/sharkey/views/navbar.slim +68 -0
- data/lib/sharkey/views/settings.slim +74 -0
- data/lib/sharkey/views/settings_index.slim +220 -0
- data/lib/sharkey/views/single_category.slim +37 -0
- data/lib/sharkey/views/single_link.slim +95 -0
- data/lib/sharkey/views/single_tag.slim +33 -0
- data/lib/sharkey/views/tag.slim +22 -0
- data/lib/sharkey/views/tagcloud.slim +54 -0
- data/lib/sharkey/views/tags.slim +99 -0
- data/sharkey-web.gemspec +44 -0
- metadata +324 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
|
|
2
|
+
require 'sharkey/models'
|
|
3
|
+
require 'deps/markio'
|
|
4
|
+
|
|
5
|
+
module Sharkey
|
|
6
|
+
|
|
7
|
+
# Knows how to import from and export to Netscape Bookmark HTML file.
|
|
8
|
+
#
|
|
9
|
+
# This format is commonly used when importing/exporting bookmarks
|
|
10
|
+
# from most browsers and tools such as Delicious.
|
|
11
|
+
#
|
|
12
|
+
# I'm using a modified version of the Ruby Gem Markio
|
|
13
|
+
# (https://github.com/spajus/markio)
|
|
14
|
+
#
|
|
15
|
+
module ImporterExporter
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# Imports all Links, their Tags and Categories from a file.
|
|
19
|
+
#
|
|
20
|
+
def import filename
|
|
21
|
+
|
|
22
|
+
# TODO Before anything, I should make sure it's a HTML file
|
|
23
|
+
# and it's not corrupted or anything...
|
|
24
|
+
|
|
25
|
+
# Opening and parsing the temporary file, all at once
|
|
26
|
+
bookmarks = File.open(filename) { |file| Markio::parse(file) }
|
|
27
|
+
|
|
28
|
+
# Now we go through all of them, creating the Categories and Links
|
|
29
|
+
bookmarks.each do |b|
|
|
30
|
+
|
|
31
|
+
# First, we make sure the categories of this Link
|
|
32
|
+
# exist.
|
|
33
|
+
#
|
|
34
|
+
# "Folder" is to "Markio" as "Categories" is to "Sharkey"
|
|
35
|
+
#
|
|
36
|
+
# `b.folders` is an array of category names, like:
|
|
37
|
+
#
|
|
38
|
+
# ["grandparent", "parent", "child"]
|
|
39
|
+
#
|
|
40
|
+
# So all we need to do is keep creating from the
|
|
41
|
+
# first to the last and the whole category hierarchy
|
|
42
|
+
# will derive.
|
|
43
|
+
#
|
|
44
|
+
last_category = nil
|
|
45
|
+
last_category_parent = nil
|
|
46
|
+
|
|
47
|
+
b.folders.each do |category_name|
|
|
48
|
+
last_category_parent = last_category
|
|
49
|
+
|
|
50
|
+
last_category = Sharkey::Category.first_or_create(name: category_name)
|
|
51
|
+
|
|
52
|
+
if last_category_parent
|
|
53
|
+
# last_category_parent.add_child last_category
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Sharkey::Link.create_link(b.title,
|
|
58
|
+
b.href,
|
|
59
|
+
b.add_date,
|
|
60
|
+
b.tags,
|
|
61
|
+
if last_category
|
|
62
|
+
then if last_category.id
|
|
63
|
+
then last_category.id
|
|
64
|
+
else nil
|
|
65
|
+
end
|
|
66
|
+
else nil
|
|
67
|
+
end,
|
|
68
|
+
"")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Exports
|
|
74
|
+
def export filename
|
|
75
|
+
# Nothing for now
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# This file contains all Models (database-thingies) of this
|
|
2
|
+
# Application.
|
|
3
|
+
#
|
|
4
|
+
# We're using DataMapper as the interface to raw SQLite
|
|
5
|
+
# databases.
|
|
6
|
+
#
|
|
7
|
+
# So here's what we do on this file:
|
|
8
|
+
#
|
|
9
|
+
# 1. Initialize DataMapper (settings 'n stuff)
|
|
10
|
+
# 2. Define the Models
|
|
11
|
+
# Specify things and columns in databases
|
|
12
|
+
# 3. Finalize DataMapper (_actually_ create the tables)
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
require 'data_mapper'
|
|
16
|
+
require 'addressable/uri'
|
|
17
|
+
|
|
18
|
+
module Sharkey
|
|
19
|
+
|
|
20
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
21
|
+
# Initializing DataMapper
|
|
22
|
+
|
|
23
|
+
# Full path to the database file
|
|
24
|
+
DATABASE_FILE = "#{Dir.pwd}/database.db"
|
|
25
|
+
DATABASE_PATH = "sqlite3://#{DATABASE_FILE}"
|
|
26
|
+
|
|
27
|
+
# By default Strings have at max 50 chars of length
|
|
28
|
+
# That's hideous! Come on!
|
|
29
|
+
DataMapper::Property::String.length 255
|
|
30
|
+
|
|
31
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
32
|
+
# Creating Models
|
|
33
|
+
|
|
34
|
+
# Represents a single HyperLink specified by the user.
|
|
35
|
+
#
|
|
36
|
+
class Link
|
|
37
|
+
# This tells that it is a thing that will get stored
|
|
38
|
+
# on the database
|
|
39
|
+
# Below are all the database elements
|
|
40
|
+
include DataMapper::Resource
|
|
41
|
+
|
|
42
|
+
property :id, Serial # Auto-incremented key
|
|
43
|
+
property :url, URI, :required => true # Actual URL
|
|
44
|
+
property :title, String # User-specified title
|
|
45
|
+
property :added_at, DateTime # When this link was added
|
|
46
|
+
property :comment, Text
|
|
47
|
+
property :favorite, Boolean, :default => false
|
|
48
|
+
property :visit_count, Integer, :default => 0
|
|
49
|
+
property :last_visit, DateTime
|
|
50
|
+
|
|
51
|
+
has n, :taggings
|
|
52
|
+
has n, :tags, :through => :taggings
|
|
53
|
+
|
|
54
|
+
has 1, :categorization
|
|
55
|
+
has 1, :category, :through => :categorization
|
|
56
|
+
|
|
57
|
+
# Creates a new Link with specified parameters.
|
|
58
|
+
#
|
|
59
|
+
# @note Link#create is a reserved method for DataMapper
|
|
60
|
+
# it actually inserts it on the database.
|
|
61
|
+
# This function differs from it on the sense that
|
|
62
|
+
# it also creates the Tags related to this Link
|
|
63
|
+
#
|
|
64
|
+
# @param tags Array of Strings as tag names
|
|
65
|
+
# @param added_at DateTime object or `nil` for DateTime.now
|
|
66
|
+
# @param category An ID of _existing_ category
|
|
67
|
+
#
|
|
68
|
+
def self.create_link(title, url, added_at, tags, category, comment)
|
|
69
|
+
# Silently fail
|
|
70
|
+
return if url.nil?
|
|
71
|
+
|
|
72
|
+
# Do not allow relative URLs!
|
|
73
|
+
# Always assume HTTP
|
|
74
|
+
if Addressable::URI.parse(url).relative?
|
|
75
|
+
url = "http://#{url}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# This array will contain the Tags objects
|
|
79
|
+
# created here
|
|
80
|
+
the_tags = []
|
|
81
|
+
if (not tags.nil?) and (not tags.empty?)
|
|
82
|
+
tags.each do |tag|
|
|
83
|
+
|
|
84
|
+
# If Sharkey::Tag exists, return it.
|
|
85
|
+
# Otherwise, create it
|
|
86
|
+
the_tags << Sharkey::Tag.first_or_create(name: tag)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Actually populating the database with
|
|
91
|
+
# a new Link
|
|
92
|
+
Sharkey::Link.create(title: title || "",
|
|
93
|
+
url: url,
|
|
94
|
+
added_at: added_at || DateTime.now,
|
|
95
|
+
tags: the_tags,
|
|
96
|
+
category: Sharkey::Category.get(category),
|
|
97
|
+
comment: comment || "")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def self.update_link(id, title, url, tags, category, comment)
|
|
101
|
+
return if id.nil? or url.nil?
|
|
102
|
+
|
|
103
|
+
# This array will contain the Tags objects
|
|
104
|
+
# created here
|
|
105
|
+
the_tags = []
|
|
106
|
+
if (not tags.nil?) and (not tags.empty?)
|
|
107
|
+
tags.each do |tag|
|
|
108
|
+
|
|
109
|
+
# If Sharkey::Tag exists, return it.
|
|
110
|
+
# Otherwise, create it
|
|
111
|
+
the_tags << Sharkey::Tag.first_or_create(name: tag)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
Sharkey::Link.get(id).update(title: title,
|
|
116
|
+
url: url,
|
|
117
|
+
tags: the_tags,
|
|
118
|
+
category: Sharkey::Category.get(category),
|
|
119
|
+
comment: comment || "");
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Returns all Links that have a Tag with `tag_id`
|
|
124
|
+
def self.by_tag(tag_id)
|
|
125
|
+
|
|
126
|
+
# RANT: I don't know why I couldn't simply do something like
|
|
127
|
+
# `Sharkey::Link.all(:tag => Sharkey::Tag.get(tag_id))`
|
|
128
|
+
# it seems so strange!
|
|
129
|
+
# DataMapper's docs imply that we actually _can_,
|
|
130
|
+
# so why...?
|
|
131
|
+
|
|
132
|
+
taggings = Sharkey::Tagging.all(:tag_id => tag_id)
|
|
133
|
+
|
|
134
|
+
Sharkey::Link.all(:taggings => taggings)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Returns all Links that have a Category with `category_id`
|
|
138
|
+
def self.by_category(category_id)
|
|
139
|
+
|
|
140
|
+
# RANT: I don't know why I couldn't simply do something like
|
|
141
|
+
# `Sharkey::Link.all(:category => Sharkey::Category.get(category_id))`
|
|
142
|
+
# it seems so strange!
|
|
143
|
+
# DataMapper's docs imply that we actually _can_,
|
|
144
|
+
# so why...?
|
|
145
|
+
|
|
146
|
+
categorizations = Sharkey::Categorization.all(:category_id => category_id)
|
|
147
|
+
|
|
148
|
+
Sharkey::Link.all(:categorization => categorizations)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def toggle_favorite
|
|
152
|
+
self.update(favorite: (not self.favorite));
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Tells if this link was ever visited
|
|
156
|
+
def visited?
|
|
157
|
+
self.visit_count != 0
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Increases the visit count by one
|
|
161
|
+
def visit
|
|
162
|
+
self.update(last_visit: DateTime.now);
|
|
163
|
+
self.update(visit_count: (self.visit_count + 1));
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Single textual tag Links can have
|
|
168
|
+
#
|
|
169
|
+
class Tag
|
|
170
|
+
include DataMapper::Resource
|
|
171
|
+
|
|
172
|
+
property :id, Serial
|
|
173
|
+
property :name, String, :required => true
|
|
174
|
+
|
|
175
|
+
has n, :taggings
|
|
176
|
+
has n, :links, :through => :taggings
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# The actual action of tagging Links.
|
|
180
|
+
#
|
|
181
|
+
# This is necessary because we can query both
|
|
182
|
+
# of them:
|
|
183
|
+
# - All Links of a Tag
|
|
184
|
+
# - All Tags of a Link
|
|
185
|
+
#
|
|
186
|
+
class Tagging
|
|
187
|
+
include DataMapper::Resource
|
|
188
|
+
|
|
189
|
+
belongs_to :tag, :key => true
|
|
190
|
+
belongs_to :link, :key => true
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Category for Links.
|
|
194
|
+
#
|
|
195
|
+
# While a Link can have several Tags, it can only
|
|
196
|
+
# have a single Category.
|
|
197
|
+
#
|
|
198
|
+
# Think of it as a folder on your Bookmarks browser.
|
|
199
|
+
#
|
|
200
|
+
# A category can have _one_ parent and _many_ children.
|
|
201
|
+
#
|
|
202
|
+
class Category
|
|
203
|
+
include DataMapper::Resource
|
|
204
|
+
|
|
205
|
+
property :id, Serial
|
|
206
|
+
property :name, String, :required => true
|
|
207
|
+
property :description, Text
|
|
208
|
+
|
|
209
|
+
has n, :categorizations
|
|
210
|
+
has n, :links, :through => :categorizations
|
|
211
|
+
|
|
212
|
+
# Access the parent through Category.parent
|
|
213
|
+
has 1, :categoryParent, :child_key => [ :source_id ]
|
|
214
|
+
has 1, :parent, self, :through => :categoryParent, :via => :target
|
|
215
|
+
|
|
216
|
+
# Access the childs through Category.childs
|
|
217
|
+
has n, :categoryChilds, :child_key => [ :source_id ]
|
|
218
|
+
has n, :childs, self, :through => :categoryChilds, :via => :target
|
|
219
|
+
|
|
220
|
+
def add_child child
|
|
221
|
+
return if (child.nil?) or (child == self) or (has_child? child)
|
|
222
|
+
return if (child.parent) and (child.parent == self)
|
|
223
|
+
|
|
224
|
+
self.childs << child
|
|
225
|
+
child.parent = self
|
|
226
|
+
|
|
227
|
+
self.save
|
|
228
|
+
self
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def has_child? child
|
|
232
|
+
self.childs.member? child
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Removes the parent/children relationship
|
|
236
|
+
# @note Does not remove any Categories!
|
|
237
|
+
def remove_child child
|
|
238
|
+
throw 'Removing self as child' if child == self
|
|
239
|
+
|
|
240
|
+
if self.categoryChilds
|
|
241
|
+
self.categoryChilds.all(target_id: child.id).destroy
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
if child.categoryParent
|
|
245
|
+
if child.categoryParent.source_id == self.id
|
|
246
|
+
child.categoryParent.destroy
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
self.reload
|
|
251
|
+
self
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def self.orphans
|
|
255
|
+
all.select { |me| me.parent.nil? }
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
class CategoryParent
|
|
260
|
+
include DataMapper::Resource
|
|
261
|
+
|
|
262
|
+
belongs_to :source, 'Category', :key => true
|
|
263
|
+
belongs_to :target, 'Category', :key => true
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
class CategoryChild
|
|
267
|
+
include DataMapper::Resource
|
|
268
|
+
|
|
269
|
+
belongs_to :source, 'Category', :key => true
|
|
270
|
+
belongs_to :target, 'Category', :key => true
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
class Categorization
|
|
274
|
+
include DataMapper::Resource
|
|
275
|
+
|
|
276
|
+
belongs_to :category, :key => true
|
|
277
|
+
belongs_to :link, :key => true
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
281
|
+
# Create Tables
|
|
282
|
+
|
|
283
|
+
# This method must be called after ALL models
|
|
284
|
+
# have been created and BEFORE the app starts
|
|
285
|
+
DataMapper.finalize
|
|
286
|
+
|
|
287
|
+
# Starting out the SQLite Database
|
|
288
|
+
DataMapper.setup(:default,
|
|
289
|
+
ENV['DATABASE_URL'] || DATABASE_PATH)
|
|
290
|
+
|
|
291
|
+
# Creates Tables if they doesn't exist
|
|
292
|
+
# Tries to adapt new models to already-existing ones...
|
|
293
|
+
DataMapper.auto_upgrade!
|
|
294
|
+
end
|
|
295
|
+
|
|
Binary file
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multiple Selection Component for Bootstrap
|
|
3
|
+
* Check nicolasbize.github.io/magicsuggest/ for latest updates.
|
|
4
|
+
*
|
|
5
|
+
* Author: Nicolas Bize
|
|
6
|
+
* Created: Feb 8th 2013
|
|
7
|
+
* Last Updated: Jun 3rd 2014
|
|
8
|
+
* Version: 2.0.5
|
|
9
|
+
* Licence: MagicSuggest is licenced under MIT licence (http://opensource.org/licenses/MIT)
|
|
10
|
+
*/
|
|
11
|
+
.ms-ctn{
|
|
12
|
+
position: relative;
|
|
13
|
+
padding: 5px 12px;
|
|
14
|
+
height: auto;
|
|
15
|
+
}
|
|
16
|
+
.ms-inv{
|
|
17
|
+
border: 1px solid #CC0000;
|
|
18
|
+
}
|
|
19
|
+
.ms-ctn-readonly{
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
}
|
|
22
|
+
.ms-ctn-disabled{
|
|
23
|
+
cursor: not-allowed;
|
|
24
|
+
background-color: #eeeeee;
|
|
25
|
+
}
|
|
26
|
+
.ms-ctn-bootstrap-focus,
|
|
27
|
+
.ms-ctn-bootstrap-focus .ms-res-ctn{
|
|
28
|
+
border-color: rgba(82, 168, 236, 0.8) !important;
|
|
29
|
+
/* IE6-9 */
|
|
30
|
+
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
|
|
31
|
+
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
|
|
32
|
+
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) !important;
|
|
33
|
+
border-bottom-left-radius: 0;
|
|
34
|
+
border-bottom-right-radius: 0;
|
|
35
|
+
}
|
|
36
|
+
.ms-ctn-focus{
|
|
37
|
+
border-color: #66afe9;
|
|
38
|
+
outline: 0;
|
|
39
|
+
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
|
|
40
|
+
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
|
|
41
|
+
}
|
|
42
|
+
.ms-ctn input{
|
|
43
|
+
border: 0;
|
|
44
|
+
box-shadow: none;
|
|
45
|
+
-webkit-transition: none;
|
|
46
|
+
outline: none;
|
|
47
|
+
display: block;
|
|
48
|
+
padding: 0;
|
|
49
|
+
line-height: 1.42857143;
|
|
50
|
+
margin: 1px 0;
|
|
51
|
+
width: 100%;
|
|
52
|
+
}
|
|
53
|
+
.ms-ctn .ms-sel-ctn input{
|
|
54
|
+
float: left;
|
|
55
|
+
}
|
|
56
|
+
.ms-ctn-disabled input{
|
|
57
|
+
cursor: not-allowed;
|
|
58
|
+
background-color: #eeeeee;
|
|
59
|
+
}
|
|
60
|
+
.ms-ctn .ms-input-readonly{
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
}
|
|
63
|
+
.ms-ctn .ms-empty-text{
|
|
64
|
+
color: #DDD;
|
|
65
|
+
}
|
|
66
|
+
.ms-ctn input:focus{
|
|
67
|
+
border: 0;
|
|
68
|
+
box-shadow: none;
|
|
69
|
+
-webkit-transition: none;
|
|
70
|
+
background: #FFF;
|
|
71
|
+
}
|
|
72
|
+
.ms-ctn input::-ms-clear {
|
|
73
|
+
width: 0;
|
|
74
|
+
height: 0;
|
|
75
|
+
}
|
|
76
|
+
.ms-ctn .ms-trigger{
|
|
77
|
+
top: 0;
|
|
78
|
+
width: 25px;
|
|
79
|
+
height:100%;
|
|
80
|
+
position:absolute;
|
|
81
|
+
right:0;
|
|
82
|
+
background: transparent;
|
|
83
|
+
border-left: 1px solid #CCC;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
}
|
|
86
|
+
.ms-ctn .ms-trigger .ms-trigger-ico {
|
|
87
|
+
display: inline-block;
|
|
88
|
+
width: 0;
|
|
89
|
+
height: 0;
|
|
90
|
+
vertical-align: top;
|
|
91
|
+
border-top: 4px solid #333;
|
|
92
|
+
border-right: 4px solid transparent;
|
|
93
|
+
border-left: 4px solid transparent;
|
|
94
|
+
content: "";
|
|
95
|
+
margin-left: 8px;
|
|
96
|
+
margin-top: 15px;
|
|
97
|
+
}
|
|
98
|
+
.ms-ctn .ms-trigger:hover{
|
|
99
|
+
background-color: #e6e6e6;
|
|
100
|
+
}
|
|
101
|
+
.ms-ctn .ms-trigger:hover .ms-trigger-ico{
|
|
102
|
+
background-position: 0 -4px;
|
|
103
|
+
}
|
|
104
|
+
.ms-ctn-disabled .ms-trigger{
|
|
105
|
+
cursor: not-allowed;
|
|
106
|
+
background-color: #eeeeee;
|
|
107
|
+
}
|
|
108
|
+
.ms-ctn-bootstrap-focus{
|
|
109
|
+
border-bottom: 1px solid #CCC;
|
|
110
|
+
}
|
|
111
|
+
.ms-res-ctn{
|
|
112
|
+
width: 100%;
|
|
113
|
+
display: block;
|
|
114
|
+
overflow-y: auto;
|
|
115
|
+
}
|
|
116
|
+
.ms-res-ctn .ms-res-group{
|
|
117
|
+
line-height: 23px;
|
|
118
|
+
text-align: left;
|
|
119
|
+
padding: 2px 5px;
|
|
120
|
+
font-weight: bold;
|
|
121
|
+
border-bottom: 1px dotted #CCC;
|
|
122
|
+
border-top: 1px solid #CCC;
|
|
123
|
+
background: #f3edff;
|
|
124
|
+
color: #333;
|
|
125
|
+
}
|
|
126
|
+
.ms-res-ctn .ms-res-item{
|
|
127
|
+
line-height: 25px;
|
|
128
|
+
text-align: left;
|
|
129
|
+
padding: 2px 5px;
|
|
130
|
+
color: #666;
|
|
131
|
+
cursor: pointer;
|
|
132
|
+
}
|
|
133
|
+
.ms-res-ctn .ms-res-item-grouped{
|
|
134
|
+
padding-left: 15px;
|
|
135
|
+
}
|
|
136
|
+
.ms-res-ctn .ms-res-odd{
|
|
137
|
+
background: #FAFAFA;
|
|
138
|
+
}
|
|
139
|
+
.ms-res-ctn .ms-res-item-active{
|
|
140
|
+
background-color: #F5F5F5;
|
|
141
|
+
}
|
|
142
|
+
.ms-sel-ctn{
|
|
143
|
+
overflow: auto;
|
|
144
|
+
line-height: 18px;
|
|
145
|
+
padding-right: 25px;
|
|
146
|
+
}
|
|
147
|
+
.ms-no-trigger .ms-sel-ctn{
|
|
148
|
+
padding-right: 0;
|
|
149
|
+
}
|
|
150
|
+
/** Outer and global tags **/
|
|
151
|
+
.ms-sel-ctn .ms-sel-item{
|
|
152
|
+
background: #F3F3F3;
|
|
153
|
+
color: #999;
|
|
154
|
+
float: left;
|
|
155
|
+
font-size: 12px;
|
|
156
|
+
padding: 3px 5px;
|
|
157
|
+
border-radius: 3px;
|
|
158
|
+
border: 1px solid #DDD;
|
|
159
|
+
margin: 3px 0px 1px 0;
|
|
160
|
+
}
|
|
161
|
+
.ms-sel-ctn .ms-sel-invalid{
|
|
162
|
+
border-color: rgb(248, 165, 165) !important;
|
|
163
|
+
background: #FDF2F2 !important;
|
|
164
|
+
}
|
|
165
|
+
.ms-sel-ctn .ms-sel-item:hover{
|
|
166
|
+
border: 1px solid #BBB;
|
|
167
|
+
}
|
|
168
|
+
/** For inner tags **/
|
|
169
|
+
.ms-ctn .ms-sel-item{
|
|
170
|
+
background: #F3F3F3;
|
|
171
|
+
color: #999;
|
|
172
|
+
float: left;
|
|
173
|
+
font-size: 12px;
|
|
174
|
+
padding: 0 5px;
|
|
175
|
+
border-radius: 3px;
|
|
176
|
+
border: 1px solid #DDD;
|
|
177
|
+
margin: 1px 5px 1px 0;
|
|
178
|
+
}
|
|
179
|
+
.ms-ctn .ms-sel-item:hover{
|
|
180
|
+
border: 1px solid transparent;
|
|
181
|
+
}
|
|
182
|
+
.ms-ctn-focus .ms-sel-item:hover{
|
|
183
|
+
border: 1px solid #BBB;
|
|
184
|
+
}
|
|
185
|
+
.ms-sel-ctn .ms-sel-text{
|
|
186
|
+
background: #FFF;
|
|
187
|
+
color: #666;
|
|
188
|
+
padding-right: 0;
|
|
189
|
+
margin-left: 0;
|
|
190
|
+
font-size: 14px;
|
|
191
|
+
font-weight: normal;
|
|
192
|
+
}
|
|
193
|
+
.ms-as-string .ms-sel-text{
|
|
194
|
+
border-color: transparent;
|
|
195
|
+
}
|
|
196
|
+
.ms-res-ctn .ms-res-item em{
|
|
197
|
+
font-style: normal;
|
|
198
|
+
background: #565656;
|
|
199
|
+
color: #FFF;
|
|
200
|
+
}
|
|
201
|
+
.ms-sel-ctn .ms-sel-text:hover{
|
|
202
|
+
background: #FFF;
|
|
203
|
+
}
|
|
204
|
+
.ms-sel-ctn .ms-sel-item-active{
|
|
205
|
+
border: 1px solid red;
|
|
206
|
+
background: #757575;
|
|
207
|
+
}
|
|
208
|
+
.ms-stacked .ms-sel-item{
|
|
209
|
+
float: inherit;
|
|
210
|
+
}
|
|
211
|
+
.ms-sel-ctn .ms-sel-item .ms-close-btn{
|
|
212
|
+
width: 7px;
|
|
213
|
+
cursor: pointer;
|
|
214
|
+
height: 7px;
|
|
215
|
+
float: right;
|
|
216
|
+
margin: 6px 2px 0 10px;
|
|
217
|
+
background-image: url(data:image/png;base64,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);
|
|
218
|
+
background-position: 0 -7px;
|
|
219
|
+
}
|
|
220
|
+
.ms-sel-ctn .ms-sel-item .ms-close-btn:hover{
|
|
221
|
+
background-position: 0 0;
|
|
222
|
+
}
|
|
223
|
+
.ms-stacked .ms-sel-item .ms-close-btn {
|
|
224
|
+
margin-left: 0px;
|
|
225
|
+
}
|
|
226
|
+
.ms-helper{
|
|
227
|
+
color: #AAA;
|
|
228
|
+
font-size: 10px;
|
|
229
|
+
position: absolute;
|
|
230
|
+
top: -17px;
|
|
231
|
+
right: 0;
|
|
232
|
+
}
|