I am trying to figure out how I can change the font-family below and still trigger the event that fits the text in the given width. When I type a long string, then change font-family... the new font family's characters extended outside the area. See photo attached.
This code uses the inputfit.js which fits text to a specific area by increasing/decreasing font size when new text is added. The clone font-family isn't changing and font size doesn't change unless keyup or keydown. I've been at this for hours now and I can't seem to make it work. Any help would be greatly appreciated.
// http://vadim.sikora.name/jquery.inputfit.js
// jquery.inputfit.js with modifications
// global define:true
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}
(function ($) {
$.fn.inputfit = function(options) {
var settings = $.extend({
minSize : 10,
maxSize : 150,
}, options);
this.each(function() {
var $input = $(this);
if ( !$input.is(':input') ) {
return;
}
$input.off('keyup.inputfit keydown.inputfit');
var maxSize = parseFloat(settings.maxSize || $input.css('font-size'), 10);
var width = $input.width();
var clone = $input.data('inputfit-clone'); // why do I need clone?
if (!clone) {
clone = $('<div></div>', {
css : {
fontSize : $input.css('font-size'),
fontFamily : $input.css('font-family'),
fontStyle : $input.css('font-style'),
fontWeight : $input.css('font-weight'),
fontVariant : $input.css('font-variant'),
letterSpacing: $input.css('letter-spacing'),
whiteSpace : 'pre', // counts the spaces on the ends, use to be 'nowrap' *modification*
position : 'absolute',
left : '-9999px',
visibility : 'hidden'
}
}).insertAfter($input);
$input.data('inputfit-clone', clone);
}
// how do I make text fit after font family changes?? clone font family not changing
// clone.css('font-family', $input.css('font-family')); ????
$input.on('keyup.inputfit keydown.inputfit', function() {
var $this = $(this);
clone.text($this.val());
var ratio = width / (clone.width() || 1),
currentFontSize = parseInt( $this.css('font-size'), 10 ),
fontSize = Math.floor(currentFontSize * ratio);
if (fontSize > maxSize) {
fontSize = maxSize;
}
if (fontSize < settings.minSize) {
fontSize = settings.minSize;
}
$this.css('font-size', fontSize);
clone.css('font-size', fontSize);
}).triggerHandler('keyup.inputfit');
});
return this;
};
}));
$(document).ready(function(){
$('#input').inputfit();
$(window).resize(function(){
$('#input').inputfit();
});
});
$(function () {
$('select[name="font"]').on('change', function () {
$('input[name="input"]').css('font-family', this.value);
});
$('select[name="color"]').on('change', function () {
$('input[name="input"]').css('color', this.value);
});
});
body {
overflow-x: hidden;
overflow-y: auto;
}
input:focus {
outline: none;
}
section {
text-align: center;
}
input {
width: 100%;
height: 300px;
text-align: center;
border-width: 0;
font-family: "Berkshire Swash";
color: #00000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jquery.inputfit.js</title>
<link href="https://fonts.googleapis.com/css?family=Arimo|Berkshire+Swash|Fredoka+One|Pacifico" rel="stylesheet">
</head>
<body>
<input id="input" name="input" value="Type Here" type="text" maxlength="100" spellcheck="false">
<section>
<select name="font">
<option value="Berkshire Swash">Berkshire Swash</option>
<option value="Pacifico">Pacifico</option>
<option value="Fredoka One">Fredoka One</option>
<option value="Arimo">Arimo</option>
</select>
<select name="color">
<option value="#000000">black</option>
<option value="#0000ff">blue</option>
<option value="#ff0000">red</option>
<option value="#ffff00">yellow</option>
</select>
</section>
</body>
</html>
You could do this by "triggering" keyup. By triggering keyup, inputfit will be ran.
$('select[name="font"]').on('change', function () {
$('input[name="input"]').css('font-family', this.value);
$("#input").trigger("keyup");
});
I have a element which has an integer count.
<span class="likes-count"> 2 </span>
And a div when clicked have to toggle the increment and decrement of the value.
<div class="liked"></div>
Problem:
I have called a function on $('.liked').clicked which increments the value and changes the class to .notliked
And another onclick function decrements the value, but it's not working properly.
Please review my code. I guess this is not the best way to do this.
Here's my demo code.
$(document).ready(function() {
$(".notliked").click(function() {
var $this = $(this);
$this.removeClass('notliked');
$this.addClass('liked')
$count = $('.likes-count');
$count.html((parseInt($count.html(),10) || 0) + 1);
});
$(".liked").click(function() {
var $this = $(this);
$this.removeClass('liked');
$this.addClass('notliked');
$count = $('.likes-count');
$count.html((parseInt($count.html(),10) || 0) - 1);
});
});
.heart {
color: #fff;
height:50px;
cursor:pointer;
width:50px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span class="likes-count"> 2 </span>
<div class="liked heart">Click</div>
You need to delegate the click event. At the beginning $(".notliked") returns 0 elements and so it's never executed.
In order to increment/decrement the text value you can use:
.text( function ) like:
$count.text(function(idx, txt) {
// convert text to number and increment by one
return +txt + 1;
});
The snippet:
$(document).on('click', ".notliked", function() {
var $this = $(this);
$this.removeClass('notliked');
$this.addClass('liked')
$count = $('.likes-count');
$count.text(function(idx, txt) {
return +txt + 1;
});
});
$(document).on('click', ".liked", function() {
var $this = $(this);
$this.removeClass('liked');
$this.addClass('notliked');
$count = $('.likes-count');
$count.text(function(idx, txt) {
return (+txt == 0) ? 0 : (+txt - 1);
});
});
.heart {
color: #fff;
height:50px;
cursor:pointer;
width:50px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="likes-count"> 0 </span>
<div class="liked heart">Click</div>
I have two divs that are overlapping using Bootstrap's 2.3.2 grid system when the browser is resized. The result looks like the following after you downsize the browser window:
I don't want the two divs to ever overlap. If it comes to a point where they cannot fit on the same row, the second div should fall below the first, which the responsive layout is already doing. My problem is those weird few pixels where they overlap.
I'm using Bootstrap's tags input library here.
The HTML:
<div class="container-fluid">
<div class="row-fluid">
<div class="span12" style="border: 1px solid black;">
<div class="span1 offset4" style="border: 1px solid blue;">
<select id="container" multiple data-role="tagsinput"> </select>
</div>
<div class="span2 offset2" style="border: 1px solid red;">
<h4>
Second Div
</h4>
<div id="second_div">
<p>
testing...... 1 ... 2 ... 3...
</p>
</div>
</div>
</div>
</div>
</div>
JavaScript to populate some dummy data:
$(document).ready(function() {
$('select').tagsinput('add', 'Foo');
$('select').tagsinput('add', 'Bar');
$('select').tagsinput('add', 'This is a very very very very very very long filter');
});
And my CSS:
.small {
font-size: 10px;
}
.tag {
/*height: 25px;*/
vertical-align: middle;
line-height: 25px;
/*width: 75%;*/
word-wrap: break-word;
white-space: normal;
}
ul {
list-style-type: none;
}
.top-margin {
margin-top: 5px;
}
.bootstrap-tagsinput {
width: 200px;
max-width: none;
}
I have a jsfiddle which demos the problem here: https://jsfiddle.net/brseyg6c/
The problem is not Bootstrap but instead this declaration:
.bootstrap-tagsinput {
width: 200px;
max-width: none;
}
You're fixing the width of the tag container while it's inside a dynamically sized Bootstrap column.
Instead, have the container fill the width of the column:
.bootstrap-tagsinput {
box-sizing: border-box;
width: 100%;
}
You might want to increase the width of the left column (change span1 to be larger) and remove the offset from the right column.
I have two idea for you.
Trick 1: Can you make it like this with out media query just replace the off-set2 and make offset3. and add this into class .bootstrap-tagsinput .tag white-space:pre-wrap; .otherwise in snippet large tag came out of the box. Trick 2 Fiddle
.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;
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 6px;
margin: 0;
width: auto;
max-width: inherit;
}
.bootstrap-tagsinput.form-control input::-moz-placeholder {
color: #777;
opacity: 1;
}
.bootstrap-tagsinput.form-control input:-ms-input-placeholder {
color: #777;
}
.bootstrap-tagsinput.form-control input::-webkit-input-placeholder {
color: #777;
}
.bootstrap-tagsinput input:focus {
border: none;
box-shadow: none;
}
.bootstrap-tagsinput .tag {
margin-top: 5px;
/* custom */
margin-right: 2px;
color: white;
white-space:pre-wrap;
}
.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);
}
body {
padding: 20px;
}
h1, h2, h3, h4, h5, h6 {
text-shadow: 1px 1px 1px #fff;
color: #000;
font-weight: bold;
line-height: 1.5;
margin: 0;
}
pre {
border-radius: 3px;
overflow-x: scroll;
}
p {
color: #000;
}
p a {
color: #990033;
text-decoration: none;
transition: all .25s;
padding: 3px;
}
p a:hover {
color: #fff;
background: #990033;
transition: all .25s;
}
ul,
ol {
margin-top: -10px;
}
.white {
color: white;
}
.small {
font-size: 10px;
}
.tag {
/*height: 25px;*/
vertical-align: middle;
line-height: 25px;
/*width: 75%;*/
word-wrap: break-word;
white-space: normal;
}
ul {
list-style-type: none;
}
.top-margin {
margin-top: 5px;
}
.bootstrap-tagsinput {
width: 200px;
max-width: none;
}
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" ></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/2.3.2/js/bootstrap.min.js" ></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css" />
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12" style="border: 1px solid black;">
<div class="span1 offset4" style="border: 1px solid blue;">
<select id="container" multiple data-role="tagsinput"> </select>
</div>
<div class="span2 offset3" style="border: 1px solid red;">
<h4>
Second Div
</h4>
<div id="event-log">
<p>
testing...... 1 ... 2 ... 3...
</p>
</div>
</div>
</div>
</div>
</div>
</body>
(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);
},
itemTitle: function(item) {
return null;
},
freeInput: true,
addOnBlur: true,
maxTags: undefined,
maxChars: undefined,
confirmKeys: [13, 44],
delimiter: ',',
delimiterRegex: null,
cancelConfirmKeysOnEmpty: true,
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 = $('<div class="bootstrap-tagsinput"></div>');
this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
this.$element.before(this.$container);
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, options) {
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 delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter;
var items = item.split(delimiter);
if (items.length > 1) {
for (var i = 0; i < items.length; i++) {
this.add(items[i], true);
}
if (!dontPushVal)
self.pushVal();
return;
}
}
var itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item),
itemTitle = self.options.itemTitle(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;
// raise beforeItemAdd arg
var beforeItemAddEvent = $.Event('beforeItemAdd', {
item: item,
cancel: false,
options: options
});
self.$element.trigger(beforeItemAddEvent);
if (beforeItemAddEvent.cancel)
return;
// register item in internal array and map
self.itemsArray.push(item);
// add a tag element
var $tag = $('<span class="tag ' + htmlEncode(tagClass) + (itemTitle !== null ? ('" title="' + itemTitle) : '') + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
$tag.data('item', item);
self.findInputWrapper().before($tag);
$tag.after(' ');
// add <option /> if item represents a value not present in one of the <select />'s options
if (self.isSelect && !$('option[value="' + encodeURIComponent(itemValue) + '"]', self.$element)[0]) {
var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
$option.data('item', item);
$option.attr('value', itemValue);
self.$element.append($option);
}
if (!dontPushVal)
self.pushVal();
// Add class when reached maxTags
if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
self.$container.addClass('bootstrap-tagsinput-max');
self.$element.trigger($.Event('itemAdded', {
item: item,
options: options
}));
},
/**
* Removes the given item. Pass true to dontPushVal to prevent updating the
* elements val()
*/
remove: function(item, dontPushVal, options) {
var self = this;
if (self.objectItems) {
if (typeof item === "object")
item = $.grep(self.itemsArray, function(other) {
return self.options.itemValue(other) == self.options.itemValue(item);
});
else
item = $.grep(self.itemsArray, function(other) {
return self.options.itemValue(other) == item;
});
item = item[item.length - 1];
}
if (item) {
var beforeItemRemoveEvent = $.Event('beforeItemRemove', {
item: item,
cancel: false,
options: options
});
self.$element.trigger(beforeItemRemoveEvent);
if (beforeItemRemoveEvent.cancel)
return;
$('.tag', self.$container).filter(function() {
return $(this).data('item') === item;
}).remove();
$('option', self.$element).filter(function() {
return $(this).data('item') === item;
}).remove();
if ($.inArray(item, self.itemsArray) !== -1)
self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
}
if (!dontPushVal)
self.pushVal();
// Remove class when reached maxTags
if (self.options.maxTags > self.itemsArray.length)
self.$container.removeClass('bootstrap-tagsinput-max');
self.$element.trigger($.Event('itemRemoved', {
item: item,
options: options
}));
},
/**
* Removes all items
*/
removeAll: function() {
var self = this;
$('.tag', self.$container).remove();
$('option', self.$element).remove();
while (self.itemsArray.length > 0)
self.itemsArray.pop();
self.pushVal();
},
/**
* Refreshes the tags so they match the text/value of their corresponding
* item.
*/
refresh: function() {
var self = this;
$('.tag', self.$container).each(function() {
var $tag = $(this),
item = $tag.data('item'),
itemValue = self.options.itemValue(item),
itemText = self.options.itemText(item),
tagClass = self.options.tagClass(item);
// Update tag's class and inner text
$tag.attr('class', null);
$tag.addClass('tag ' + htmlEncode(tagClass));
$tag.contents().filter(function() {
return this.nodeType == 3;
})[0].nodeValue = htmlEncode(itemText);
if (self.isSelect) {
var option = $('option', self.$element).filter(function() {
return $(this).data('item') === item;
});
option.attr('value', itemValue);
}
});
},
/**
* Returns the items added as tags
*/
items: function() {
return this.itemsArray;
},
/**
* Assembly value by retrieving the value of each item, and set it on the
* element.
*/
pushVal: function() {
var self = this,
val = $.map(self.items(), function(item) {
return self.options.itemValue(item).toString();
});
self.$element.val(val, true).trigger('change');
},
/**
* Initializes the tags input behaviour on the element
*/
build: function(options) {
var self = this;
self.options = $.extend({}, defaultOptions, options);
// When itemValue is set, freeInput should always be false
if (self.objectItems)
self.options.freeInput = false;
makeOptionItemFunction(self.options, 'itemValue');
makeOptionItemFunction(self.options, 'itemText');
makeOptionFunction(self.options, 'tagClass');
// Typeahead Bootstrap version 2.3.2
if (self.options.typeahead) {
var typeahead = self.options.typeahead || {};
makeOptionFunction(typeahead, 'source');
self.$input.typeahead($.extend({}, typeahead, {
source: function(query, process) {
function processItems(items) {
var texts = [];
for (var i = 0; i < items.length; i++) {
var text = self.options.itemText(items[i]);
map[text] = items[i];
texts.push(text);
}
process(texts);
}
this.map = {};
var map = this.map,
data = typeahead.source(query);
if ($.isFunction(data.success)) {
// support for Angular callbacks
data.success(processItems);
} else if ($.isFunction(data.then)) {
// support for Angular promises
data.then(processItems);
} else {
// support for functions and jquery promises
$.when(data)
.then(processItems);
}
},
updater: function(text) {
self.add(this.map[text]);
return this.map[text];
},
matcher: function(text) {
return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
},
sorter: function(texts) {
return texts.sort();
},
highlighter: function(text) {
var regex = new RegExp('(' + this.query + ')', 'gi');
return text.replace(regex, "<strong>$1</strong>");
}
}));
}
// typeahead.js
if (self.options.typeaheadjs) {
var typeaheadConfig = null;
var typeaheadDatasets = {};
// Determine if main configurations were passed or simply a dataset
var typeaheadjs = self.options.typeaheadjs;
if ($.isArray(typeaheadjs)) {
typeaheadConfig = typeaheadjs[0];
typeaheadDatasets = typeaheadjs[1];
} else {
typeaheadDatasets = typeaheadjs;
}
self.$input.typeahead(typeaheadConfig, typeaheadDatasets).on('typeahead:selected', $.proxy(function(obj, datum) {
if (typeaheadDatasets.valueKey)
self.add(datum[typeaheadDatasets.valueKey]);
else
self.add(datum);
self.$input.typeahead('val', '');
}, self));
}
self.$container.on('click', $.proxy(function(event) {
if (!self.$element.attr('disabled')) {
self.$input.removeAttr('disabled');
}
self.$input.focus();
}, self));
if (self.options.addOnBlur && self.options.freeInput) {
self.$input.on('focusout', $.proxy(function(event) {
// HACK: only process on focusout when no typeahead opened, to
// avoid adding the typeahead text as tag
if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
self.add(self.$input.val());
self.$input.val('');
}
}, self));
}
self.$container.on('keydown', 'input', $.proxy(function(event) {
var $input = $(event.target),
$inputWrapper = self.findInputWrapper();
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
switch (event.which) {
// BACKSPACE
case 8:
if (doGetCaretPosition($input[0]) === 0) {
var prev = $inputWrapper.prev();
if (prev.length) {
self.remove(prev.data('item'));
}
}
break;
// DELETE
case 46:
if (doGetCaretPosition($input[0]) === 0) {
var next = $inputWrapper.next();
if (next.length) {
self.remove(next.data('item'));
}
}
break;
// LEFT ARROW
case 37:
// Try to move the input before the previous tag
var $prevTag = $inputWrapper.prev();
if ($input.val().length === 0 && $prevTag[0]) {
$prevTag.before($inputWrapper);
$input.focus();
}
break;
// RIGHT ARROW
case 39:
// Try to move the input after the next tag
var $nextTag = $inputWrapper.next();
if ($input.val().length === 0 && $nextTag[0]) {
$nextTag.after($inputWrapper);
$input.focus();
}
break;
default:
// ignore
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
self.$container.on('keypress', 'input', $.proxy(function(event) {
var $input = $(event.target);
if (self.$element.attr('disabled')) {
self.$input.attr('disabled', 'disabled');
return;
}
var text = $input.val(),
maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
// Only attempt to add a tag if there is data in the field
if (text.length !== 0) {
self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
$input.val('');
}
// If the field is empty, let the event triggered fire as usual
if (self.options.cancelConfirmKeysOnEmpty === false) {
event.preventDefault();
}
}
// Reset internal input's size
var textLength = $input.val().length,
wordSpace = Math.ceil(textLength / 5),
size = textLength + wordSpace + 1;
$input.attr('size', Math.max(this.inputSize, $input.val().length));
}, self));
// Remove icon clicked
self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
if (self.$element.attr('disabled')) {
return;
}
self.remove($(event.target).closest('.tag').data('item'));
}, self));
// Only add existing value as tags when using strings as tags
if (self.options.itemValue === defaultOptions.itemValue) {
if (self.$element[0].tagName === 'INPUT') {
self.add(self.$element.val());
} else {
$('option', self.$element).each(function() {
self.add($(this).attr('value'), true);
});
}
}
},
/**
* Removes all tagsinput behaviour and unregsiter all event handlers
*/
destroy: function() {
var self = this;
// Unbind events
self.$container.off('keypress', 'input');
self.$container.off('click', '[role=remove]');
self.$container.remove();
self.$element.removeData('tagsinput');
self.$element.show();
},
/**
* Sets focus on the tagsinput
*/
focus: function() {
this.$input.focus();
},
/**
* Returns the internal input element
*/
input: function() {
return this.$input;
},
/**
* Returns the element which is wrapped around the internal input. This
* is normally the $container, but typeahead.js moves the $input element.
*/
findInputWrapper: function() {
var elt = this.$input[0],
container = this.$container[0];
while (elt && elt.parentNode !== container)
elt = elt.parentNode;
return $(elt);
}
};
/**
* Register JQuery plugin
*/
$.fn.tagsinput = function(arg1, arg2, arg3) {
var results = [];
this.each(function() {
var tagsinput = $(this).data('tagsinput');
// Initialize a new tags input
if (!tagsinput) {
tagsinput = new TagsInput(this, arg1);
$(this).data('tagsinput', tagsinput);
results.push(tagsinput);
if (this.tagName === 'SELECT') {
$('option', $(this)).attr('selected', 'selected');
}
// Init tags from $(this).val()
$(this).val($(this).val());
} else if (!arg1 && !arg2) {
// tagsinput already exists
// no function, trying to init
results.push(tagsinput);
} else if (tagsinput[arg1] !== undefined) {
// Invoke function on existing tags input
if (tagsinput[arg1].length === 3 && arg3 !== undefined) {
var retVal = tagsinput[arg1](arg2, null, arg3);
} else {
var retVal = tagsinput[arg1](arg2);
}
if (retVal !== undefined)
results.push(retVal);
}
});
if (typeof arg1 == 'string') {
// Return the results from the invoked function calls
return results.length > 1 ? results : results[0];
} else {
return results;
}
};
$.fn.tagsinput.Constructor = TagsInput;
/**
* Most options support both a string or number as well as a function as
* option value. This function makes sure that the option with the given
* key in the given options is wrapped in a function
*/
function makeOptionItemFunction(options, key) {
if (typeof options[key] !== 'function') {
var propertyName = options[key];
options[key] = function(item) {
return item[propertyName];
};
}
}
function makeOptionFunction(options, key) {
if (typeof options[key] !== 'function') {
var value = options[key];
options[key] = function() {
return value;
};
}
}
/**
* HtmlEncodes the given value
*/
var htmlEncodeContainer = $('<div />');
function htmlEncode(value) {
if (value) {
return htmlEncodeContainer.text(value).html();
} else {
return '';
}
}
/**
* Returns the position of the caret in the given input field
* http://flightschool.acylt.com/devnotes/caret-position-woes/
*/
function doGetCaretPosition(oField) {
var iCaretPos = 0;
if (document.selection) {
oField.focus();
var oSel = document.selection.createRange();
oSel.moveStart('character', -oField.value.length);
iCaretPos = oSel.text.length;
} else if (oField.selectionStart || oField.selectionStart == '0') {
iCaretPos = oField.selectionStart;
}
return (iCaretPos);
}
/**
* Returns boolean indicates whether user has pressed an expected key combination.
* #param object keyPressEvent: JavaScript event object, refer
* http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
* #param object lookupList: expected key combinations, as in:
* [13, {which: 188, shiftKey: true}]
*/
function keyCombinationInList(keyPressEvent, lookupList) {
var found = false;
$.each(lookupList, function(index, keyCombination) {
if (typeof(keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
found = true;
return false;
}
if (keyPressEvent.which === keyCombination.which) {
var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
if (alt && shift && ctrl) {
found = true;
return false;
}
}
});
return found;
}
/**
* Initialize tagsinput behaviour on inputs and selects which have
* data-role=tagsinput
*/
$(function() {
$("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
});
})(window.jQuery);
$(document).ready(function() {
$('select').tagsinput('add', 'Another Model');
$('select').tagsinput('add', 'TestCam7');
$('select').tagsinput('add', 'TestCam4');
$('select').tagsinput('add', 'Profanity');
$('select').tagsinput('add', 'An Anddress');
$('select').tagsinput('add', 'This is a very very very very very very long filter');
});
Trick's 2: Using this 2 media query only you can achieve the same output. Trick's 2 fiddle
#media (min-width: 1076px) and (min-width: 979px) {
.row-fluid .span2 {
margin-left: 15.5%;
}
}
#media (max-width: 979px) and (min-width: 768px) {
.row-fluid .span2 {
margin-left: 25.5%;
}
}
I am using a little Javascript navigation bar for my single-page site. All of my text links work just fine, but the outbound social media links on the right side are not responding (unless you secondary-click and open it from there). Now, I am just barely knowledgable in JQuery and Javascript...I can understand it and how it works but when it comes to errors I can't figure it out. Thank you for helping! :)
Here is my CSS:
.single-page-nav {
background: rgb(255, 255, 255);
background: rgba(255, 255, 255, .9);
padding: 1.25em 0;
box-shadow: 0px 2px 8px #555;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index:100000;
}
.single-page-nav ul {
list-style: none;
padding: 0;
margin: 0 auto;
margin-left: -30px;
width: 80%;
overflow: hidden;
}
.single-page-nav li {
float: left;
width: 16%;
text-align: center;
}
.single-page-nav a {
display: block;
color: #000;
font-family: 'Calibri', Helvetica, Sans-Serif;
text-decoration: none;
font-size: 18px;
font-weight: bold;
line-height:1.5em;
}
.single-page-nav a:hover,
.single-page-nav .current {
color: #F92F2C;
}
Here is my HTML
<nav id="menu" role="navigation">
<div class="single-page-nav">
<ul>
<li>Page Top</li>
<li>Watch the Video</li>
<li>Kickstarter</li>
<li>About the Project</li>
<li>Meet the Team</li>
<li>What Are We Doing?</li>
</ul>
<span id="socialtop1">
<img src="/wp-content/images/emailg.png" alt="Email" />
</span>
<span id="socialtop2">
<img src="/wp-content/images/ytg.png" alt="YouTube" />
</span>
<span id="socialtop3">
<img src="/wp-content/images/vmg.png" alt="Vimeo" />
</span>
<span id="socialtop4">
<img src="/wp-content/images/instag.png" alt="Instagram" />
</span>
<span id="socialtop5">
<img src="/wp-content/images/twg.png" alt="Twitter" />
</span>
<span id="socialtop6">
<img src="/wp-content/images/fbg.png" alt="Facebook" />
</span>
</div>
</nav>
And, last but not least, here is the JQuery/Javascript. I didn't write most of it, it's from a tutorial I used.
// Utility
if (typeof Object.create !== 'function') {
Object.create = function(obj) {
function F() {}
F.prototype = obj;
return new F();
};
}
(function($, window, document, undefined) {
"use strict";
var SinglePageNav = {
init: function(options, container) {
this.options = $.extend({}, $.fn.singlePageNav.defaults, options);
this.container = container;
this.$container = $(container);
this.$links = this.$container.find('a');
if (this.options.filter !== '') {
this.$links = this.$links.filter(this.options.filter);
}
this.$window = $(window);
this.$htmlbody = $('html, body');
this.$links.on('click.singlePageNav', $.proxy(this.handleClick, this));
this.didScroll = false;
this.checkPosition();
this.setTimer();
},
handleClick: function(e) {
var self = this,
link = e.currentTarget,
$elem = $(link.hash);
e.preventDefault();
if ($elem.length) { // Make sure the target elem exists
// Prevent active link from cycling during the scroll
self.clearTimer();
// Before scrolling starts
if (typeof self.options.beforeStart === 'function') {
self.options.beforeStart();
}
self.setActiveLink(link.hash);
self.scrollTo($elem, function() {
if (self.options.updateHash) {
document.location.hash = link.hash;
}
self.setTimer();
// After scrolling ends
if (typeof self.options.onComplete === 'function') {
self.options.onComplete();
}
});
}
},
scrollTo: function($elem, callback) {
var self = this;
var target = self.getCoords($elem).top;
var called = false;
self.$htmlbody.stop().animate(
{scrollTop: target},
{
duration: self.options.speed,
complete: function() {
if (typeof callback === 'function' && !called) {
callback();
}
called = true;
}
}
);
},
setTimer: function() {
var self = this;
self.$window.on('scroll.singlePageNav', function() {
self.didScroll = true;
});
self.timer = setInterval(function() {
if (self.didScroll) {
self.didScroll = false;
self.checkPosition();
}
}, 250);
},
clearTimer: function() {
clearInterval(this.timer);
this.$window.off('scroll.singlePageNav');
this.didScroll = false;
},
// Check the scroll position and set the active section
checkPosition: function() {
var scrollPos = this.$window.scrollTop();
var currentSection = this.getCurrentSection(scrollPos);
this.setActiveLink(currentSection);
},
getCoords: function($elem) {
return {
top: Math.round($elem.offset().top) - this.options.offset
};
},
setActiveLink: function(href) {
var $activeLink = this.$container.find("a[href='" + href + "']");
if (!$activeLink.hasClass(this.options.currentClass)) {
this.$links.removeClass(this.options.currentClass);
$activeLink.addClass(this.options.currentClass);
}
},
getCurrentSection: function(scrollPos) {
var i, hash, coords, section;
for (i = 0; i < this.$links.length; i++) {
hash = this.$links[i].hash;
if ($(hash).length) {
coords = this.getCoords($(hash));
if (scrollPos >= coords.top - this.options.threshold) {
section = hash;
}
}
}
// The current section or the first link
return section || this.$links[0].hash;
}
};
$.fn.singlePageNav = function(options) {
return this.each(function() {
var singlePageNav = Object.create(SinglePageNav);
singlePageNav.init(options, this);
});
};
$.fn.singlePageNav.defaults = {
offset: 0,
threshold: 120,
speed: 400,
currentClass: 'current',
updateHash: false,
filter: '',
onComplete: false,
beforeStart: false
};
})(jQuery, window, document);
The problem is that your javascript drastically changes the default link behavior inside of the single-page-nav container. It is applying this javascript functionality to your external links as well, which you do NOT want to have in order for them to work properly.
This bit e.preventDefault(); in your javascript prevents the browser from handling the click event normally.
To fix your problem I would apply the class single-page-nav to the ul (since your social links are outside of this ul) and tweak your CSS a bit.
Personally, I would change the CSS something like so:
.topnav { ... }
.single-page-nav { ... }
.single-page-nav li { ... }
.topnav a { ... }
.topnav a:hover, .topnav .current { ... }
The code below is (hopefully) a minimized testcase of my original problem. I'm trying to set up a system where you drag list items from the left menu (draggable items) and then drop'em to the box on the right hand side. Once they're dropped, you should be able to click the "draggable item" text and expand their fieldsets.
The problem is, however, that once you have dropped the items and clicked to expand them (say you have 3 items), the first one will give you 3 alert boxes, the second one will give you 2 and the last one will only give you 1. In other words, from the top, it will give you x alert boxes (where X is the number of items).
Looking at the code, I really can't figure out why this happens, other than it seems that having the .click stuff inside stop: seems to be related, given the fact that the example on http://api.jquery.com/click/ works fine.
(BTW: The stuff inside the alert box is supposed to be the ID of the item you clicked.)
Any ideas?
<!doctype>
<html>
<head>
<title>testcase</title>
<style type="text/css">
body { padding: 50px; font-family: Arial; font-size: .9em }
#column, #data { float: left }
#column { width: 13% }
ul, ol { padding: 0; border: 0 }
li { list-style: none }
.droptarget { padding: 10px; border: 1px solid #999; height: 10px; width: 350px; margin-right: 1.2% }
.ui-draggable-dragging, .ui-sortable-helper { background: #f90; width: 100px; display: block }
</style>
<script src="http://code.jquery.com/jquery-1.4.1.js" type="text/javascript" charset="utf-8"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
function hideAllElements() {
var elements = $('.dtContent');
var elementsLength = elements.length
for (var j = 0; j < elementsLength; j++) {
elements[j].style.display = 'none';
}
}
var randNum = 0;
function randNoDups() {
tmpRand = randNum;
while (tmpRand == randNum) {
tmpRand = Math.round(Math.random() * 50000000);
}
randNum = tmpRand;
return tmpRand;
}
$(function () {
var i = 0;
$(".draggable").draggable({
connectToSortable: ".sortable",
helper: 'clone'
});
$(".contentGroupList").sortable({
connectWith: '.contentGroupList',
stop: function (event, ui) {
var currentId = ui.item.children(0).attr('id');
var currentNumber = currentId.split("dt");
var randomKey = randNoDups();
ui.item.children(0).attr({
id: ui.item.children(0).attr('id') + randomKey
});
if ((i + 1) == $('.droptarget').children().size()) {
hideAllElements();
var $formContainer = $('<fieldset>').addClass('dtContent').attr({
id: 'fs' + currentNumber[1] + randomKey
});
var $table = $('<table>').appendTo($formContainer);
var $submit = $('<input>').attr({type: 'submit'}).appendTo($formContainer);
ui.item.append($formContainer);
ui.item.attr({id: 'listItem' + i});
$("span").click(function () { alert($(this).attr('id')); });
i++;
}
}
});
});
</script>
</head>
<body>
<div id="column">
<ul id="draggables">
<li class="draggable"><span class="dt" id="dt0">Draggable item</span></li>
</ul>
</div>
<div id="contentGroups-1" class="contentGroup">
<ul class="droptarget sortable contentGroupList"></ul>
</div>
</body>
</html>
The problem is probably here:
$("span").click(function () { alert($(this).attr('id')); });
This will find every span in the document and alert it's id. Try using the ui object instead:
ui.item.click(function() {
alert(this.id);
});