I'm working with JQuery & JQuery UI.
I followed the example on the JQuery UI demos for the custom rendering to add icons to the select menu items which is working well. What I'm having trouble with is adding the selected icon to the button that the user clicks to show the menu. I followed the accepted answer found here, and I've got an icon showing, but it doesn't show the custom icon I want it to, it shows one of the standard icons. I've tried many different variations for the CSS and adding classes to the span for the icon, but I can't get it right. When I inspect the element in Chrome, it always shows the image as being derived from the 'ui-button ui-icon' class, not my custom icon class. What combination of CSS and classes to I need to make it show correctly?
I've got a selectmenu defined as follows:
<select name="sourceIcon" id="jsSourceIconSelect">
<option value="AM-FM-2" data-class="am-fm">AM-FM</option>
<option value="CD-2" data-class="cd">CD</option>
<option value="Climate-2" data-class="climate">Climate</option>
<option value="Display-Alt-2" data-class="display-alt">Display Alt</option>
<option value="Display-2" data-class="display">Display</option>
<option value="DVR-2" data-class="dvr">DVR</option>
<option value="Energy Management-2" data-class="energy-management">Energy Management</option>
<option value="Favorites-2" data-class="favorites">Favorites</option>
<option value="Film Reel-2" data-class="film-reel">Film Reel</option>
<option value="Home-2" data-class="home">Home</option>
</select>
and the associated javascript:
$.widget("custom.iconselectmenu", $.ui.selectmenu, {
_renderItem: function(ul, item) {
var li = $("<li>"),
wrapper = $("<div>",{text: item.label});
if(item.disabled){
li.addClass("ui-state-disabled");
}
$("<span>", {
style: item.element.attr("data-style"),
"class":"ui-icon " + item.element.attr("data-class")
}).appendTo(wrapper);
return li.append(wrapper).appendTo(ul);
}
});
$("#jsSourceIconSelect").iconselectmenu({
select: function(event, ui){
$("#" + this.id + "ImgSelected").attr("class","ui-icon" + ui.item.element.data("class"));
},
create: function(event, ui){
var widget=$(this).iconselectmenu("widget");
$span = $('<span id="' + this.id + 'ImgSelected" class="ui-icon ' + $(this).children(":first").data("class") +'">').appendTo(widget);
}
})
.iconselectmenu("menuWidget")
.addClass("ui-menu-icons customicons");
and the associated css:
.ui-selectmenu-menu .ui-menu.customicons .ui-menu-item-wrapper{
padding: .5em 0 .5em 3em;
}
.ui-selectmenu-menu .ui-menu.customicons .ui-menu-item .ui-icon{
background-image: url("ui-icons-largeicons.png");
height: 32px;
width: 32px;
top: .1em;
}
edit: thought I should add the css for a few of the icons:
.ui-icon.am-fm{ background-position: 0 0; }
.ui-icon.cd{ background-position: -32px 0; }
.ui-icon.climate{ background-position: -64px 0; }
.ui-icon.display-alt{ background-position: -96px 0;}
.ui-icon.display{ background-position: -128px 0;}
.ui-icon.dvr{background-position: -160px 0;}
.ui-icon.energy-management{ background-position: -192px 0;}
.ui-icon.favorites{background-position: -224px 0;}
.ui-icon.film-reel{background-position: -256px 0;}
.ui-icon.home{background-position: -288px 0;}
The way I handled a custom icon in selectmenu is to change position-x, position-y to normal settings because that was the reason the image wasn't shown.
I just made the following css :
.ui-icon {
background-image: url("/Images/dropdown-icon_2018-10-03/dropdown-icon.png");
background-position-x: 0;
background-position-y: 5px;
}
Using selectmenu examples as OP i came up with the following solution:
$(function () {
$.widget("custom.iconselectmenu", $.ui.selectmenu, {
_renderItem: function (ul, item) {
var li = $("<li>"),
wrapper = $("<div>", { html: item.element.html() });
if (item.disabled) {
li.addClass("ui-state-disabled");
}
$("<span>", {
style: item.element.attr("data-style"),
"class": "ui-icon " + item.element.attr("data-class")
})
.appendTo(wrapper);
return li.append(wrapper).appendTo(ul);
}
});
$("#people")
.iconselectmenu({
create: function (event, ui) {
var widget = $(this).iconselectmenu("widget");
$span = $('<span id="' + this.id + 'selected" class="avatar-selected"> ').html(" ").appendTo(widget);
$span.attr("style", $(this).children(":first").data("style"));
},
change: function (event, ui) {
$("#" + this.id + 'selected').attr("style", ui.item.element.data("style"));
}
})
.iconselectmenu("menuWidget")
.addClass("ui-menu-icons avatar");
});
and corresponding CSS:
.ui-selectmenu-menu .ui-menu.avatar .ui-menu-item-wrapper {
padding: 2px 10px 0 30px;
}
.ui-selectmenu-menu .ui-menu.avatar .ui-menu-item .ui-icon {
height: 24px;
width: 24px;
top: 0.1em;
}
.ui-selectmenu-text {
padding-left: 2em;
}
.avatar-selected {
position:absolute;
height: 24px;
width: 24px;
right:auto;
margin-top:-12px;
top:50%;
background-repeat:no-repeat;
}
Related
I have some quantity inputs. I want to collect the data in "inputs" and show them in "#yolcudropdown". But I just can't pull the data. Inputs must be disabled. There should be no manual entry. I did something at the bottom of the "javascript" section. But I couldn't run it.
(function( $ ) {
$.fn.number = function(customOptions) {
var options = {
'containerClass' : 'number-style',
'minus' : 'number-minus',
'plus' : 'number-plus',
'containerTag' : 'div',
'btnTag' : 'span'
};
options = $.extend(true, options, customOptions);
var input = this;
input.wrap('<' + options.containerTag + ' class="' + options.containerClass + '">');
var wrapper = input.parent();
wrapper.prepend('<' + options.btnTag + ' class="' + options.minus + '"></' + options.btnTag + '>');
var minus = wrapper.find('.' + options.minus);
wrapper.append('<' + options.btnTag + ' class="' + options.plus + '"></' + options.btnTag + '>');
var plus = wrapper.find('.' + options.plus);
var min = input.attr('min');
var max = input.attr('max');
if(input.attr('step')){
var step = +input.attr('step');
} else {
var step = 1;
}
if(+input.val() <= +min){
minus.addClass('disabled');
}
if(+input.val() >= +max){
plus.addClass('disabled');
}
minus.click(function () {
var input = $(this).parent().find('input');
var value = input.val();
if(+value > +min){
input.val(+value - step);
if(+input.val() === +min){
input.prev('.' + options.minus).addClass('disabled');
}
if(input.next('.' + options.plus).hasClass('disabled')){
input.next('.' + options.plus).removeClass('disabled')
}
} else if(!min){
input.val(+value - step);
}
});
plus.click(function () {
var input = $(this).parent().find('input');
var value = input.val();
if(+value < +max){
input.val(+value + step);
if(+input.val() === +max){
input.next('.' + options.plus).addClass('disabled');
}
if(input.prev('.' + options.minus).hasClass('disabled')){
input.prev('.' + options.minus).removeClass('disabled')
}
} else if(!max){
input.val(+value + step);
}
});
};
})(jQuery);
$('.quntity-input').each(function () {
$(this).number();
});
/* THIS IS IMPORTANT */
$(document).ready(function() {
$(document).on('change', '.btw', function() {
$('#yolcudropdown').text($(this).val());
});
});
.number-style {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-pack: start !important;
justify-content: flex-start !important;
-ms-flex-align: center !important;
align-items: center !important;
}
.number-style .number-minus,
.number-style .number-plus {
height: 28px;
background: #ffffff;
border: 2px solid #e2e2e2 !important;
width: 28px;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
-ms-border-radius: 100%;
border-radius: 100%;
line-height: 23px;
font-size: 19px;
font-weight: 700;
text-align: Center;
border: none;
display: block;
cursor: pointer;
}
.number-style .number-minus:active,
.number-style .number-plus:active {
background: #e2e2e2;
}
.number-style .number-minus {
line-height: 20px;
}
.number-style .number-minus::after {
content: "-";
font-size: 10px;
}
.number-style .number-plus {
line-height: 18px;
}
.number-style .number-plus::after {
content: "+";
font-size: 10px;
}
.number-style .quntity-input {
width: 28px;
background: #e00f23;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
-ms-border-radius: 100%;
border-radius: 100%;
line-height: 21px;
font-size: 14px;
color: #ffffff;
font-weight: 700;
text-align: Center;
margin: 0 5px;
display: block;
cursor: pointer;
text-align: center;
border: none;
height: 28px;
font-weight: 600;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="quntity-input btw" type="text" value="0" step="1" min="0" max="10">
<input class="quntity-input btw" type="text" value="0" step="1" min="0" max="10">
<div id="yolcudropdown">İnput quantity show this div</div>
"class" names of "input" elements are the same. I need to collect inputs with the same value and display them in the div instantly
HTMLInputElement
Input type "text" has no min max or step attributes, so your HTML is absolutely invalid. Try not to write It-works, I'm a framework -code. Respect the W3C standards.
Use type="number" (CSS pseudos can help you remove default spinner arrows from such elements)
Also step could be floats. Respect that and use parseFloat() in JS
CSS Flex to align stuff
Seems you know about CSS-flex, use it! Height, therefore- line-height... 19? 20? 23px? No. Just use flex.
CSS !important
!important is sign of poor coding style and should be left to Bootstrap only. Or to hopefully override Bootstrap styles - or in that cases when developers actually know what they are doing.
jQuery Plugins
jQuery plugins, I suggest to read the DOCS and get a deeper knowledge on how plugins work. Almost every jQuery method is a plugin. .hide() , .addClass()... I won't count them all. Plugins are chainable .removeClass("foo").stop().fadeTo(1), and so should be your .number() plugin.
To achieve chain-ability you simply return the bound this. PS: that's not jQuery... that's how JS works.
jQuery Plugins are not meant to be called inside a $.each() loop. $() is already a collection of DOM Nodes wrapped in a jQuery Object. No need to .each(). Same like: you would rather use $('a').css({color:'blue'}) instead of $('a').each(){ $(this).css({color: 'blue'}); });. Same effect, less code. Plugins.
jQuery DOM ready
jQuery(function($) { }); // DOM ready and $ alias in scope
Or if you don't care about ±IE, or you use ES6 syntax and a toolchain like Babel than: jQuery($ => { }) will suffice.
jQuery $ Object Constructor
jQuery allows you to define an HTMLElement that will eventually become a new DOM element wrapped with all the jQuery powers, Methods. Meaning that, if instead of passing a selector, you pass a more complex Tag-alike string (say: $("<span/>", {}); - jQuery will create an inMemory SPAN element and allow you to use the second parameter {} for most of the available jQuery Methods for that $Element. Let's use this!
jQuery plugin callbacks
If you want to provide a callback after a user changes the input value, provide a callback method. Don't force a programmer to write new spaghetti code, stick to the scope of your available Plugin internal Methods.
Sum Elements values
To sum Elements values you can use Array.prototype.reduce, just make sure to use an initialValue to prevent possible TypeErrors.
Example
Finally, here's the simplified CSS and improved JS:
(function($) {
$.fn.number = function(customOptions) {
const options = $.extend(true, {
containerTag: "div",
containerClass: "number-style",
minusClass: "number-minus", // consistency in wording!
minusText: "-", // Give power to the user!
plusClass: "number-plus",
plusText: "+",
btnTag: "button",
onChange() {}, // Provide a nifty callback!
}, customOptions);
this.each(function() { // Use .each() here!
const $input = $(this);
let val = parseFloat($input.value || 0); // floats!
const min = parseFloat($input.attr("min"));
const max = parseFloat($input.attr("max"));
const step = parseFloat($input.is("[step]") ? $input.attr("step") : 1);
const handleStyles = () => {
$minus.toggleClass('disabled', val <= min);
$plus.toggleClass('disabled', val >= max);
};
const change = () => {
val = Math.max(min, Math.min(max, val)); // Keep val in range.
$input.val(val); // Update input value
handleStyles(); // Update styles
options.onChange.call($input[0], val); // Trigger a public callback
}
const decrement = () => {
val -= step;
change();
};
const increment = () => {
val += step;
change();
};
const $minus = $(`<${options.btnTag}>`, {
type: "button",
title: "Decrement",
class: options.minusClass,
text: options.minusText,
on: {
click: decrement
}
});
const $plus = $(`<${options.btnTag}>`, {
class: options.plusClass,
title: "Increment",
text: options.plusText,
on: {
click: increment
}
});
const $wrapper = $(`<${options.containerTag}>`, {
class: options.containerClass,
});
$input.after($wrapper);
$wrapper.append($minus, $input.detach(), $plus); // Append all
handleStyles(); // handle initial styles
});
return this; // make your plugin chainable!
};
})(jQuery);
jQuery(function($) { // DOM ready and $ alias in scope
const $quantityInp = $('.quantity-input'); // Cache your elements!
const $dropdown = $('#yolcudropdown'); // Cache your elements!
$quantityInp.number({
onChange(val) { // our custom onChange callback!
const tot = $quantityInp.get().reduce((acc, el) => {
acc += parseFloat(el.value);
return acc;
}, 0);
$dropdown.text(tot);
}
});
});
/* QuickReset */ * { margin:0; box-sizing:border-box; }
.number-style input::-webkit-outer-spin-button,
.number-style input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.number-style {
display: flex;
}
.number-style > * {
height: 2em;
min-width: 2em;
border-radius: 2em;
display: flex; /* Use flex. */
justify-content: center;
text-align: center;
border: 0;
background: #ddd;
}
.number-style button {
background: #fff;
box-shadow: inset 0 0 0 2px #ccc;
cursor: pointer;
user-select: none;
/* no highlight, please! */
}
.number-style button:active {
background: #0bf;
}
.number-style input {
background: #e00f23;
color: #fff;
margin: 0 5px;
}
.number-style .disabled {
opacity: 0.2;
cursor: default;
}
/* Custom overrides: */
.number-style>* {
width: 2em;
/* just for roundness */
}
<input class="quantity-input" type="number" value="0" step="1" min="0" max="10">
<input class="quantity-input" type="number" value="0" step="1" min="0" max="10">
<div id="yolcudropdown">0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Additional reading:
HTMLInputElement
Math/min
Math/max
jQuery plugin-creation
$ new-elements
Array/reduce
jQuery.toggleClass()
And PS: it's "quantity", not "quntity"
I am trying to show a description when hovering over an option in a select list, however, I am having trouble getting the code to recognize when hovering.
Relevant code:
Select chunk of form:
<select name="optionList" id="optionList" onclick="rankFeatures(false)" size="5"></select>
<select name="ranks" id="ranks" size="5"></select>
Manipulating selects (arrays defined earlier):
function rankFeatures(create) {
var $optionList = $("#optionList");
var $ranks = $("#ranks");
if(create == true) {
for(i=0; i<5; i++){
$optionList.append(features[i]);
};
}
else {
var index = $optionList.val();
$('#optionList option:selected').remove();
$ranks.append(features[index]);
};
}
This all works. It all falls apart when I try to deal with hovering over options:
$(document).ready(
function (event) {
$('select').hover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
})
})
I found that code while searching through Stack Exchange, yet I am having no luck getting it to work. The alert occurs when I click on an option. If I don't move the mouse and close the alert by hitting enter, it goes away. If I close out with the mouse a second alert window pops up. Just moving the mouse around the select occasionally results in an alert box popping up.
I have tried targeting the options directly, but have had little success with that. How do I get the alert to pop up if I hover over an option?
You can use the mouseenter event.
And you do not have to use all this code to check if the element is an option.
Just use the .on() syntax to delegate to the select element.
$(document).ready(function(event) {
$('select').on('mouseenter','option',function(e) {
alert('yeah');
// this refers to the option so you can do this.value if you need..
});
});
Demo at http://jsfiddle.net/AjfE8/
try with mouseover. Its working for me. Hover also working only when the focus comes out from the optionlist(like mouseout).
function (event) {
$('select').mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
})
})
You don't need to rap in in a function, I could never get it to work this way. When taking it out works perfect. Also used mouseover because hover is ran when leaving the target.
$('option').mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
console.log('yeah!');
};
})
Fiddle to see it working. Changed it to console so you don't get spammed with alerts. http://jsfiddle.net/HMDqb/
That you want is to detect hover event on option element, not on select:
$(document).ready(
function (event) {
$('#optionList option').hover(function(e) {
console.log(e.target);
});
})
I have the same issue, but none of the solutions are working.
$("select").on('mouseenter','option',function(e) {
$("#show-me").show();
});
$("select").on('mouseleave','option',function(e) {
$("#show-me").hide();
});
$("option").mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
});
Here my jsfiddle https://jsfiddle.net/ajg99wsm/
I would recommend to go for a customized variant if you like to ease
capture hover events
change hover color
same behavior for "drop down" and "all items" view
plus you can have
resizeable list
individual switching between single selection and multiple selection mode
more individual css-ing
multiple lines for option items
Just have a look to the sample attached.
$(document).ready(function() {
$('.custopt').addClass('liunsel');
$(".custopt, .custcont").on("mouseover", function(e) {
if ($(this).attr("id") == "crnk") {
$("#ranks").css("display", "block")
} else {
$(this).addClass("lihover");
}
})
$(".custopt, .custcont").on("mouseout", function(e) {
if ($(this).attr("id") == "crnk") {
$("#ranks").css("display", "none")
} else {
$(this).removeClass("lihover");
}
})
$(".custopt").on("click", function(e) {
$(".custopt").removeClass("lihover");
if ($("#btsm").val() == "ssm") {
//single select mode
$(".custopt").removeClass("lisel");
$(".custopt").addClass("liunsel");
$(this).removeClass("liunsel");
$(this).addClass("lisel");
} else if ($("#btsm").val() == "msm") {
//multiple select mode
if ($(this).is(".lisel")) {
$(this).addClass("liunsel");
$(this).removeClass("lisel");
} else {
$(this).addClass("lisel");
$(this).removeClass("liunsel");
}
}
updCustHead();
});
$(".custbtn").on("click", function() {
if ($(this).val() == "ssm") {
$(this).val("msm");
$(this).text("switch to single-select mode")
} else {
$(this).val("ssm");
$(this).text("switch to multi-select mode")
$(".custopt").removeClass("lisel");
$(".custopt").addClass("liunsel");
}
updCustHead();
});
function updCustHead() {
if ($("#btsm").val() == "ssm") {
if ($(".lisel").length <= 0) {
$("#hrnk").text("current selected option");
} else {
$("#hrnk").text($(".lisel").text());
}
} else {
var numopt = +$(".lisel").length,
allopt = $(".custopt").length;
$("#hrnk").text(numopt + " of " + allopt + " selected option" + (allopt > 1 || numopt === 0 ? 's' : ''));
}
}
});
body {
text-align: center;
}
.lisel {
background-color: yellow;
}
.liunsel {
background-color: lightgray;
}
.lihover {
background-color: coral;
}
.custopt {
margin: .2em 0 .2em 0;
padding: .1em .3em .1em .3em;
text-align: left;
font-size: .7em;
border-radius: .4em;
}
.custlist,
.custhead {
width: 100%;
text-align: left;
padding: .1em;
border: LightSeaGreen solid .2em;
border-radius: .4em;
height: 4em;
overflow-y: auto;
resize: vertical;
user-select: none;
}
.custlist {
display: none;
cursor: pointer;
}
.custhead {
resize: none;
height: 2.2em;
font-size: .7em;
padding: .1em .4em .1em .4em;
margin-bottom: -.2em;
width: 95%;
}
.custcont {
width: 7em;
padding: .5em 1em .6em .5em;
/* border: blue solid .2em; */
margin: 1em auto 1em auto;
}
.custbtn {
font-size: .7em;
width: 105%;
}
h3 {
margin: 1em 0 .5em .3em;
font-weight: bold;
font-size: 1em;
}
ul {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>
customized selectable, hoverable resizeable dropdown with multi-line, single-selection and multiple-selection support
</h3>
<div id="crnk" class="custcont">
<div>
<button id="btsm" class="custbtn" value="ssm">switch to multi-select mode</button>
</div>
<div id="hrnk" class="custhead">
current selected option
</div>
<ul id="ranks" class="custlist">
<li class="custopt">option one</li>
<li class="custopt">option two</li>
<li class="custopt">another third long option</li>
<li class="custopt">another fourth long option</li>
</ul>
</div>
There're next HTML:
<div class="garden">
<div class="point left">◄</div>
<div class="trees">
<div id="apple">Apple</div>
<div id="cherry">Cherry</div>
<div id="pear">Pear</div>
<div id="oak">Oak</div>
<div id="fir">Fir</div>
</div>
<div class="point right">►</div>
</div>
And CSS:
.garden { position: absolute; top: 135px; left: 150px; }
.garden > div { display:inline-block; }
.trees { width:550px; height:53px; position:relative; font-size:70%; }
.point { width: 16px; height: 15px; background: url(/point-sprite.png) no-repeat;}
.point.left { background-position: -16px 0; }
.point:hover { background-position: 0 0; }
.point.right { background-position: -32px 0; }
.point:hover { background-position: -48px 0 }
.trees > div span { min-width:50px; position:absolute; display:inline-block; top:25px; left:15px; text-align:center; }
#apple, #cherry, #pear, #oak, #fir { position: absolute; color: #0094d9; }
#apple { top: 10px; }
#cherry { top: 2px; left: 90px; }
#pear { left: 180px; }
#oak { left: 280px; }
#fir { top: 2px; left: 373px; }
I need to change the position of the elements to the left after each clicking "point left". And to the right after each clicking "poin right". When an item has a position of leftmost and click "point left" then this item should go right to the rightmost position. One great man (https://stackoverflow.com/users/2121519/stuart-miller) help me to creat next script:
JS
$(document).ready(function () {
function changePositionLeft() {
var trees = $('#trees');
trees.children().each( function(index, child) {
if (index == 0) {
$(child).animate(trees.children().last().position());
}
else {
$(child).animate(trees.children().eq(index - 1).position());
}
});
trees.children().first().appendTo(trees);
}
$(".point.left").click(function() {
changePositionLeft();
});
});
Help transform it according to my task with using .clone. Thanks in advance
Link for script: http://jsfiddle.net/8kkfw7mu/5/
You want us to code the changePositionRight function?
If so, here it is.
I kept the same structure as the changePositionLeft method, but changed the following:
if (index == trees.children().length -1) {
$(child).animate(trees.children().first().position());
}
Instead of targetting the first element and putting it in the last position, we target the last one, and put it in first position.
Then:
else {
$(child).animate(trees.children().eq(index + 1).position());
}
Instead of moving the others elements to the previous position, move them to the next position.
Final result
Add this to your script:
function changePositionRight(){
var trees = $('#trees');
trees.children().each( function(index, child) {
if (index == trees.children().length -1) {
$(child).animate(trees.children().first().position());
}
else {
$(child).animate(trees.children().eq(index + 1).position());
}
});
trees.children().last().appendTo(trees);
}
$(".point.right").click(function() {
changePositionRight();
});
Why is this thing not working? If I remove ::before from javascript and css it works. But due to the design needs there has to be a ::before. How do I point to the class + ::before?
$(function () {
var sections = $("section");
var navigation_links = $("nav a");
sections.waypoint({
handler: function (event, direction) {
var active_section;
active_section = $(this);
if (direction === "up") active_section = active_section.prev();
var active_link = $('nav a[href="#' + active_section.attr("id") + '"]');
navigation_links.removeClass("selected::before");
active_link.addClass("selected::before");
},
offset: '25%'
})
});
css:
.selected::before {
display: block;
content: "";
margin-top: 6px;
width: 8px;
height: 8px;
background: url(../img/sprite.png) -126px -196px;
background-size: 400px 480px;
float: left;
margin-left: 20px;
margin-right: 20px;
}
You don't need to add the ::before in the JS. As long as the .selected class appears on the element, CSS will do the rest. addClass("selected::before") is telling the browser to add a class called "selected::before", which is not what you want. (I'm not even sure you are allowed to have :: in a class name, but I suspect not.)
Is there any jQuery plugin that will summarize my text i.e.:
123456789
into
1234...
However when I click that three dots it will expand it and show:
123456789
Without plugin css and jquery is welcome.
Any ideas?
There are several plugins for this, and it's so easy that you can probably create your own as well.
But, taking the work from someone else, here is a couple:
jQuery Expander Plugin
Jquery Plugin: readmore
CSS-only solution:
.truncate {
width: 250px; /* TODO: set as needed */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.truncate:hover {
white-space: normal;
overflow: visible;
text-overflow: inherit;
}
You could also rig something that'd do so on click via:
$(".truncate").click(function () { $(this).addClass("noTruncate"); }
and then change .truncate:hover to .noTruncate.
Here is a non-destructive, jQuery-binded and CSS-executed technique.
Considering this SCSS/LESS:
.collapsable {
margin-bottom: 10px; /* your <p> margin-bottom */
line-height: 20px; /* your <p> line-height */
p {
line-height: inherit;
margin-bottom: inherit;
&:last-child {
margin-bottom: 0;
}
}
&.collapsed {
position: relative;
overflow: hidden;
p {
margin: 0;
}
.expand-link-container {
position: absolute;
bottom: 0; right: 0;
display: block;
line-height: inherit;
padding: 0 2px 0 5px;
background-color: #FFF;
box-shadow: -5px 0 5px 0 white;
}
}
.expand-link-container {
display: none;
}
}
And this jQuery:
function collapseHTML(shownLines, expanderLink){
// Configuration
var shownLines = typeof(shownLines) === "undefined" ? 4 : shownLines,
expanderLink = typeof(expanderLink) === "undefined" ? "[...]" : expanderLink;
$('.collapsable').each(function(){
// If current collapsable has already been collapsed once, skip
if( $(this).find('.expand-link-container').length > 0 ) return false;
// Compute max-height from line-height and shownLines
var lineHeight = $(this).find('p').first().css('line-height');
maxHeight = parseInt(lineHeight, 10) * shownLines;
// If the current div needs collapsing
if( $(this).height() > maxHeight) {
$(this)
// Collapse it
.addClass('collapsed')
.css('max-height', maxHeight)
// Append expander link
.find('p:first-child').append(
'<div class="expand-link-container">' +
' ' + expanderLink + '' +
'</div>')
// Bind click to expander link
.find('.expand-link-container a').click(function(e){
e.preventDefault();
$(this).closest('.collapsable')
.removeClass('collapsed')
.css('max-height', '');
});
}
});
}
Calling collapseHTML() anywhere in your javascript will cause all div.collapse to collapse their HTML content.
Example in JSfiddle
I had used the Summary plugin before (http://plugins.learningjquery.com/summarize/index.html). However I do not know if it is available for the jQuery version that you are using.
You can use substr
Updated Fiddle - http://jsfiddle.net/GC2qC/1/
var ttext = $('span').text(); //Store value
$('span').text($('span').text().substr(0, 4)).append('...'); //Substring
$('body').on('click', 'span', function(){ //Display complete text
$(this).text(ttext);
});