From aa73259a479d36394cf298979dc260030062ee70 Mon Sep 17 00:00:00 2001 From: Stefan Parviainen Date: Sun, 21 Dec 2014 12:42:07 +0100 Subject: Fancy categories input with bootstrap-tagsinput --- view/css/conversation.css | 4 +-- view/php/theme_init.php | 2 ++ view/theme/redbasic/css/style.css | 58 +++++++++++++++++++++------------------ view/tpl/jot.tpl | 12 ++++---- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/view/css/conversation.css b/view/css/conversation.css index 1e9930443..7a5ffc2f7 100644 --- a/view/css/conversation.css +++ b/view/css/conversation.css @@ -8,9 +8,7 @@ code { /* jot */ -#jot-title, -#jot-category, -#jot-pagetitle { +.jothidden input { border: 0px; margin: 0px; padding: 8px; diff --git a/view/php/theme_init.php b/view/php/theme_init.php index ff8b54c55..f28f9aa8d 100644 --- a/view/php/theme_init.php +++ b/view/php/theme_init.php @@ -11,6 +11,7 @@ head_add_css('library/colorbox/colorbox.css'); head_add_css('view/css/conversation.css'); head_add_css('view/css/widgets.css'); head_add_css('library/justifiedGallery/dist/css/justifiedGallery.css'); +head_add_css('library/bootstrap-tagsinput/bootstrap-tagsinput.css'); head_add_js('jquery.js'); head_add_js('jquery-migrate-1.1.1.js'); @@ -41,6 +42,7 @@ head_add_js('crypto.js'); head_add_js('library/jslider/bin/jquery.slider.min.js'); head_add_js('docready.js'); head_add_js('library/colorbox/jquery.colorbox-min.js'); +head_add_js('library/bootstrap-tagsinput/bootstrap-tagsinput.js'); /** * Those who require this feature will know what to do with it. diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index 382bed90e..961572652 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -1746,44 +1746,23 @@ img.mail-list-sender-photo { max-width: $converse_width; } -#jot-title, -#jot-category, -#jot-pagetitle { +.jothidden { font-weight: bold; - border: solid 1px #ffffff; border-radius: $radiuspx; } -#jot-category::-webkit-input-placeholder { +.jothidden input::-webkit-input-placeholder { font-weight: bold; } -#jot-category:-moz-placeholder { +.jothidden input::-moz-placeholder { font-weight: bold; } -#jot-title::-webkit-input-placeholder { - font-weight: bold; -} - -#jot-title:-moz-placeholder { - font-weight: bold; -} - -#jot-pagetitle::-webkit-input-placeholder { - font-weight: bold; -} - -#jot-pagetitle:-moz-placeholder { - font-weight: bold; +.jothidden >input, .jothidden >input { + border: 1px solid #fff; } - -#jot-title:hover, -#jot-title:focus, -#jot-pagetitle:hover, -#jot-pagetitle:focus, -#jot-category:hover, -#jot-category:focus { +.jothidden >input:hover, .jothidden >input:focus { border: 1px solid #cccccc; } @@ -2368,3 +2347,28 @@ aside .nav > li > a:hover, aside .nav > li > a:focus { .bb_observer img { border: 3px solid red !important; } + +.bootstrap-tagsinput .tag:before { + /* Copied from icon-asterisk, is there a better way to do it? */ + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + text-decoration: inherit; + content:"\f069"; +} + +/* Modified original CSS to match input in Redbasic */ +.bootstrap-tagsinput { + border-color:#fff; + background-color: #fff; + box-shadow: none; + display: inline-block; + border-radius: $radiuspx; + cursor: text; + padding: 0 6px; + width: 70% !important; +} + +.jothidden .bootstrap-tagsinput:hover, .jothidden .bootstrap-tagsinput:focus { + border: 1px solid #cccccc; +} diff --git a/view/tpl/jot.tpl b/view/tpl/jot.tpl index 34acce879..00ef77d93 100755 --- a/view/tpl/jot.tpl +++ b/view/tpl/jot.tpl @@ -19,17 +19,17 @@ {{$id_seltext}} {{$id_select}} {{/if}} -
- + {{if $catsenabled}} -
- + {{/if}} {{if $webpage}} -
- + {{/if}}
-- cgit v1.2.3 From b8081624c5160cfda904c2a6fe2e594e8a5b779a Mon Sep 17 00:00:00 2001 From: Stefan Parviainen Date: Sun, 21 Dec 2014 12:44:57 +0100 Subject: Add bootstrap-tagsinput library --- library/bootstrap-tagsinput/LICENSE | 20 + library/bootstrap-tagsinput/README | 1 + library/bootstrap-tagsinput/README.md | 879 +++++++++++++++++++++ .../bootstrap-tagsinput/bootstrap-tagsinput.css | 46 ++ library/bootstrap-tagsinput/bootstrap-tagsinput.js | 643 +++++++++++++++ 5 files changed, 1589 insertions(+) create mode 100644 library/bootstrap-tagsinput/LICENSE create mode 100644 library/bootstrap-tagsinput/README create mode 100644 library/bootstrap-tagsinput/README.md create mode 100644 library/bootstrap-tagsinput/bootstrap-tagsinput.css create mode 100644 library/bootstrap-tagsinput/bootstrap-tagsinput.js diff --git a/library/bootstrap-tagsinput/LICENSE b/library/bootstrap-tagsinput/LICENSE new file mode 100644 index 000000000..58bc985ba --- /dev/null +++ b/library/bootstrap-tagsinput/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Tim Schlechter + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/library/bootstrap-tagsinput/README b/library/bootstrap-tagsinput/README new file mode 100644 index 000000000..a7c96d53a --- /dev/null +++ b/library/bootstrap-tagsinput/README @@ -0,0 +1 @@ +Taken from https://github.com/gdibble/bootstrap-tagsinput/tree/traditionalPlaceholderEffect which has proper support for placeholders diff --git a/library/bootstrap-tagsinput/README.md b/library/bootstrap-tagsinput/README.md new file mode 100644 index 000000000..363c0d50b --- /dev/null +++ b/library/bootstrap-tagsinput/README.md @@ -0,0 +1,879 @@ + + + + + + + + + + + + + bootstrap-tagsinput/README.md at master · TimSchlechter/bootstrap-tagsinput · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Skip to content +
+ + + + + + + + + + + +
+
+
+ +
+
+
+ + + +

+ + /bootstrap-tagsinput + + + + + +

+
+
+ +
+
+
+ + + +
+ + +
+

HTTPS clone URL

+
+ + + + +
+
+ + +
+

Subversion checkout URL

+
+ + + + +
+
+ + + +

You can clone with + HTTPS or Subversion. + + + +

+ + + + + + Download ZIP + +
+
+ +
+ + + + + + +
+ +
+ + + branch: + master + + + +
+ +
+ + + + +
+ + +
+ + +
+
+ Tim Schlechter + + + +
+ + + +
+ +
+
+
+
+ 70 lines (61 sloc) + + 3.157 kb +
+
+
+ Raw + Blame + History +
+ + + + + + + +
+
+ +
+

+Bootstrap Tags Input Build Status +

+ +

Bootstrap Tags Input is a jQuery plugin providing a Twitter Bootstrap user interface for managing tags.

+ +

+Usage

+ +

Examples can be found here.

+ +

+Features

+ +
    +
  • Objects as tags
  • +
  • True multi value
  • +
  • Typeahead
  • +
  • Designed for Bootstrap 2.3.2 and 3
  • +
+ +

+Objects as tags

+ +

Not just support for using strings! This means you can use different values +for a tag's label and value. Each tag also holds a reference to the object +by which it was created, so by calling tagsinput('items') an +array of the original items is returned.

+ +

+True multi value support

+ +

Other implementations just concatenate the values to a comma separated string. +This results in val() returning just this string, and when +submitting the form, only one big, concatenated value is sent in the request.

+ +

Bootstrap Tags Input provides true multivalue support. Just use a +<select multiple /> as your input element, and +val() will return an array of the tag values. When submitting the +form, an array of values will be sent with the request.

+ +

+Typeahead support

+ +

Integrates with Twitter Bootstraps' 2.3.2 typeahead, or use custom typeahead when using Bootstrap 3.

+ +

+Development

+ +

Install dependencies:

+ +
+npm install
+bower install
+
+ +

Test:

+ +
+grunt test
+
+ +

Build:

+ +
+grunt build
+
+ +

+History

+ + + +

+License

+ +

This project is licensed under MIT.

+
+
+ +
+
+ +Jump to Line + + +
+ +
+ +
+
+ + +
+ +
+ +
+ + +
+
+
+ +
+
+
+
+
+ +
+ + + +
+ + + Something went wrong with that request. Please try again. +
+ + + + + + + + + diff --git a/library/bootstrap-tagsinput/bootstrap-tagsinput.css b/library/bootstrap-tagsinput/bootstrap-tagsinput.css new file mode 100644 index 000000000..55f7c09df --- /dev/null +++ b/library/bootstrap-tagsinput/bootstrap-tagsinput.css @@ -0,0 +1,46 @@ +.bootstrap-tagsinput { + background-color: #fff; + border: 1px solid #ccc; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + display: inline-block; + padding: 4px 6px; + margin-bottom: 10px; + color: #555; + vertical-align: middle; + border-radius: 4px; + max-width: 100%; + line-height: 22px; + cursor: text; +} +.bootstrap-tagsinput input { + border: none; + box-shadow: none; + outline: none; + background-color: transparent; + padding: 0; + margin: 0; + width: auto !important; + max-width: inherit; +} +.bootstrap-tagsinput input:focus { + border: none; + box-shadow: none; +} +.bootstrap-tagsinput .tag { + margin-right: 2px; + color: white; +} +.bootstrap-tagsinput .tag [data-role="remove"] { + margin-left: 8px; + cursor: pointer; +} +.bootstrap-tagsinput .tag [data-role="remove"]:after { + content: "x"; + padding: 0px 2px; +} +.bootstrap-tagsinput .tag [data-role="remove"]:hover { + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} +.bootstrap-tagsinput .tag [data-role="remove"]:hover:active { + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} diff --git a/library/bootstrap-tagsinput/bootstrap-tagsinput.js b/library/bootstrap-tagsinput/bootstrap-tagsinput.js new file mode 100644 index 000000000..89cc3b5a4 --- /dev/null +++ b/library/bootstrap-tagsinput/bootstrap-tagsinput.js @@ -0,0 +1,643 @@ +(function ($) { + "use strict"; + + var defaultOptions = { + tagClass: function(item) { + return 'label label-info'; + }, + itemValue: function(item) { + return item ? item.toString() : item; + }, + itemText: function(item) { + return this.itemValue(item); + }, + freeInput: true, + addOnBlur: true, + maxTags: undefined, + maxChars: undefined, + confirmKeys: [13, 44], + onTagExists: function(item, $tag) { + $tag.hide().fadeIn(); + }, + trimValue: false, + allowDuplicates: false + }; + + /** + * Constructor function + */ + function TagsInput(element, options) { + this.itemsArray = []; + + this.$element = $(element); + this.$element.hide(); + + this.isSelect = (element.tagName === 'SELECT'); + this.multiple = (this.isSelect && element.hasAttribute('multiple')); + this.objectItems = options && options.itemValue; + this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : ''; + this.inputSize = Math.max(1, this.placeholderText.length); + + this.$container = $('
'); + this.$input = $('').appendTo(this.$container); + + this.$element.after(this.$container); + + var inputWidth = (this.inputSize < 3 ? 3 : this.inputSize) + "em"; + this.$input.get(0).style.cssText = "width: " + inputWidth + " !important;"; + this.build(options); + } + + TagsInput.prototype = { + constructor: TagsInput, + + /** + * Adds the given item as a new tag. Pass true to dontPushVal to prevent + * updating the elements val() + */ + add: function(item, dontPushVal) { + var self = this; + + if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags) + return; + + // Ignore falsey values, except false + if (item !== false && !item) + return; + + // Trim value + if (typeof item === "string" && self.options.trimValue) { + item = $.trim(item); + } + + // Throw an error when trying to add an object while the itemValue option was not set + if (typeof item === "object" && !self.objectItems) + throw("Can't add objects when itemValue option is not set"); + + // Ignore strings only containg whitespace + if (item.toString().match(/^\s*$/)) + return; + + // If SELECT but not multiple, remove current tag + if (self.isSelect && !self.multiple && self.itemsArray.length > 0) + self.remove(self.itemsArray[0]); + + if (typeof item === "string" && this.$element[0].tagName === 'INPUT') { + var items = item.split(','); + if (items.length > 1) { + for (var i = 0; i < items.length; i++) { + this.add(items[i], true); + } + + if (!dontPushVal) + self.pushVal(); + return; + } + } + + // raise beforeItemAdd arg + var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false }); + self.$element.trigger(beforeItemAddEvent); + if (beforeItemAddEvent.cancel) + return; + + item = beforeItemAddEvent.item + + var itemValue = self.options.itemValue(item), + itemText = self.options.itemText(item), + tagClass = self.options.tagClass(item); + + // Ignore items allready added + var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0]; + if (existing && !self.options.allowDuplicates) { + // Invoke onTagExists + if (self.options.onTagExists) { + var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; }); + self.options.onTagExists(item, $existingTag); + } + return; + } + + // if length greater than limit + if (self.items().toString().length + item.length + 1 > self.options.maxInputLength) + return; + + // register item in internal array and map + self.itemsArray.push(item); + + //remove placeholder if there is an item, restore if no item(s) + if (self.itemsArray.length) + self.$input.attr('placeholder', ''); + else + self.$input.attr('placeholder', self.placeholderText); + + // add a tag element + var $tag = $('' + htmlEncode(itemText) + ''); + $tag.data('item', item); + self.findInputWrapper().before($tag); + $tag.after(' '); + + // add