I need to work with several sliders in the same page. Therefore I've created a class for the sliders (so there's only one jquery code) and I want to set the max and min values to attributes of the divs. They will then change according to the slider selected.
I'm guessing to do that I would need to use this at some point, or else it will target every class. Although I have no idea where to start or where to include it.
For now I've just applied the basic code, here it is:
HTML :
<div class="slider" slider-min="15" slider-max="250" svalue="132"></div><span class="slider-value"></span>
<div class="slider" slider-min="30" slider-max="300" svalue="165"></div><span class="slider-value"></span>
<div class="slider" slider-min="100" slider-max="500" svalue="300"></div><span class="slider-value"></span>
CSS :
.ui-slider { position: relative; text-align: left; background: #DADDD8; z-index: 0; }
.ui-slider { -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; }
.ui-slider .ui-slider-handle { background: #8FB339; position: absolute; z-index: 2; width: 15px; height: 15px; border-radius:5px; cursor:pointer; }
.ui-slider .ui-state-hover, .ui-slider .ui-state-active { background: #4B5842; }
.ui-slider .ui-slider-range { background: #C7D59F; position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider .ui-slider-range { -moz-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; -webkit-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; }
.ui-slider-horizontal { height: 5px; width:100px; margin:5px auto; }
.ui-slider-horizontal .ui-slider-handle { top: -5px; margin-left: -5px; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.slider-value{
font-size:12px;
float:right;
margin-top:-16px;
margin-right:5px;
}
JS/JQUERY :
$( function() {
var div = $(".slider");
$( ".slider" ).slider({
range: "min",
slide: function( event, ui ) {
$( ".slider-value" ).html( ui.value );
},
min: div.data("slider-min"),
max: div.data("slider-max"),
value: div.data("svalue"),
})});
$( ".slider-value" ).html( $(this).slider('value') );
Here is this demo on jsfiddle
AND while I'm at it, I've got this other problem with the class/multiple sliders thing : when I want to display the current value of ONE slider, since it's a class it changes all the .slider-value spans. I do not know where to begin with this issue either.
Thank you for your time/help :)
Okay, you were on the right path, but you were throwing a few things in there that were redundant, probably from trying stuff and forgetting to remove them.
I've modified your code a little to make the function you have reusable. I've also nested the value field within the same div as the slider. This is to show you how easy jQuery makes it to find related elements, but you could relate them in other ways without having to nest them... Note that I didn't fix up the CSS, so it's a little messed up, but you can figure that out yourself...
The big change really though was the use of the id attribute, when using jQuery selectors, the 3 main types you can use (though there are others), are CSS class selectors $(".slider"), element selectors $("div"), and id selectors $("#slider1").
Just try the following changes to the HTML and JavaScript:
JavaScript / jQuery:
var func = function(div) {
var slide = $(div).slider({
range: "min",
slide: function( event, ui ) {
$(div).find(".slider-value").html( ui.value );
},
min: parseInt(div.attr("slider-min")),
max: parseInt(div.attr("slider-max")),
value: parseInt(div.attr("svalue")),
})
};
func($("#slider1"));
func($("#slider2"));
func($("#slider3"));
HTML:
<div class="slider" id="slider1" slider-min="15" slider-max="250" svalue="132"><span class="slider-value"></span>
</div>
<div class="slider" id="slider2" slider-min="30" slider-max="300" svalue="165"><span class="slider-value"></span></div>
<div class="slider" id="slider3" slider-min="100" slider-max="500" svalue="300"><span class="slider-value"></span></div>
Related
I have a model that called LinksListWidgetModel that contains an IEnumerable property named Links that contains a list of my website links.
In my Razor view, I have two columns (i.e. one for the grid "col-md-8" and one for another tool "col-md-4". I have a foreach loop that adds each link to the grid tool. I am trying to achieve the following look: Matrix View, however the buttons don't wrap after three, it just continues throughout the width of the page. I am using Bootstrap4.x and flexbox.
I tried following the example in this question: How I can make nice looking matrix of buttons with bootstrap 3?, but that didn't fix the issue either.
Here is my code:
LinksListGrid.cshtml:
#if (Model == null)
{
#Html.Partial("_WidgetNotConfigured") }
else
{
<div class="btn-group btn-matrix" role="group">
#foreach (var link in Model.Links)
{
<div class="linkContainer-gridItem">
<button>
<a class="linkContainer-gridItem-link btn btn-default" href="#link.Url">
#if (!string.IsNullOrEmpty(link.Icon))
{
<div>
<i class="icon #link.Icon"></i>
</div>
}
#link.Label
</a>
</button>
</div>
}
</div>
}
LinkContainer.scss:
.linkContainer {
padding: 1rem;
margin-bottom: 2rem;
position: relative;
background: #fff;
border-radius: 8px;
border: 1px solid #dddfe2;
.linkContainer-title {
color: #fff;
background: $colorBrandDarkBlue;
padding: 1rem;
border-radius: 5px;
margin: -.5rem -.5rem 1rem -.5rem;
font-weight: 400;
}
.linkContainer-list {
list-style: none;
padding: 0;
margin-bottom: 0;
font-family: "Montserrat",sans-serif;
.linkContainer-item {
position: relative;
.linkContainer-link {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: .75rem .5rem;
color: $colorBrandBlue;
font-weight: 400;
font-size: 18px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
text-decoration: none;
background-color: transparent;
font-family: "Montserrat",sans-serif;
}
.icon:before {
font-size: 30px;
margin-right: 1rem;
}
}
.linkContainer-item:after {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
border-top: 1px dotted;
opacity: .25;
}
}
.linkContainer-grid {
width: 290px;
display: block;
margin: 0 auto;
padding: 0;
padding-bottom: 19px;
font-family: "Montserrat",sans-serif;
text-align: center;
.linkContainer-gridItem {
background-color: $colorBrandBlue;
border-radius: 25px;
width: 120px;
height: 120px;
margin: 10px;
display: inline-block;
vertical-align: top;
.linkContainer-gridItem-link {
color: white;
text-decoration: none;
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
padding: 20px 10px;
}
.icon {
font-size: 30px;
margin-bottom: 0.25rem;
}
}
}
#media screen and (max-width: 767px) {
&.linkContainer-gridLayout {
padding: 0;
}
}
}
.btn-matrix {
> .btn {
&:nth-child(3n+4) {
clear: left;
margin-left: 0;
}
&:nth-child(n+4) {
margin-top: -1px;
}
&:first-child {
border-bottom-left-radius: 0;
}
&:nth-child(3) {
border-top-right-radius: 4px !important;
}
&:nth-last-child(3) {
border-bottom-left-radius: 4px !important;
}
&:last-child {
border-top-right-radius: 0;
}
}
}
It ends up looking like this: Grid View
How can I change this to make it look like the first screenshot's matrix/grid display? After every 3 buttons it goes on the second line.
I don't think clear:left; will work on flexbox. But there are other ways to do it.
HTML & SCSS way
I think you would be better off just styling .btn-matrix yourself, without mixing .btn-group styles, because Bootstrap .btn-group brings in lots of noice on its .btn children, such as border-radius, border, etc. You would need to style them using your own styles anyway so why bother.
I think the following structure should be generic enough you can use to construct a matrix:
<div class="btn-matrix btn-matrix-white" role="group">
<a class="btn" href="#">
<div class="fa-stack fa-2x">
<i class="fas fa-circle fa-stack-2x" />
<i class="fas fa-chart-bar fa-stack-1x" />
</div>
Reports
</a>
...
</div>
First of all, in your original HTML structure, you had a button that wraps an anchor link. That's not necessary because Bootstrap has classes to style an anchor link to just look like a button.
Secondly, I am using icon stacking method to construct icons with circle backgrounds. You can read about it here: https://fontawesome.com/how-to-use/on-the-web/styling/stacking-icons
Finally, here is the styles:
$numOfMatrixItemPerRow: 3;
$matrixItemBorderWidth: 1px;
.btn-matrix {
display: flex;
flex-flow: row wrap;
box-shadow: 0 0 1rem #ccc;
border: 1px solid transparent;
border-radius: .25rem;
> .btn {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: flex-start;
flex-grow: 0;
flex-shrink: 0;
padding: 5%;
width: calc(100% / #{$numOfMatrixItemPerRow});
border-radius: 0;
}
&.btn-matrix-white {
> .btn {
background-color: #fff;
border-right: $matrixItemBorderWidth solid #ddd;
border-bottom: $matrixItemBorderWidth solid #ddd;
.fa-stack-2x {
color: var(--primary);
}
.fa-stack-1x {
color: #fff;
}
&:nth-child(#{$numOfMatrixItemPerRow}n) {
border-right: none !important;
}
&:last-child {
border-bottom: none !important;
}
}
}
}
Really nothing tricky there except you would need to use SASS Interpolation to involve $numOfMatrixItemPerRow variable into calculations:
Display .btn-matrix as a wrappable flex row
Set the width of each button to be 100% / $numOfMatrixItemPerRow so that each row will contain the exact number of items before breaking into new rows
Display .btn as flexbox column so that you can easily align the icons and text there
Set the right and bottom border of each button, with exceptions of the last one on each row and last one
demo: https://jsfiddle.net/davidliang2008/1wqost69/201/
ASP.NET MVC way
Now since you're using ASP.NET MVC, I think there is another approach you can consider. That is, in the loop where you loop though each link from the model, you can define a variable there and do something like:
<div class="btn-matrix">
#for (int i = 0; i < Model.Links.Count(); i++)
{
var link = Model.Links[i];
if (i % numOfItemsPerRow == 0)
{
<div class="row">
}
<div class="col-md-4">
<a class="btn" href="#link.Url">
#if (!string.IsNullOrEmpty(link.Icon))
{
<div>
<i class="icon #link.Icon"></i>
</div>
}
#link.Label
</a>
</div>
if ((i+1) % numOfItemsPerRow == 0 || i + 1 == Model.Links.Count())
{
</div>
}
}
</div>
I'm just making things up but hopefully you see where I am going.
I wrote some kind of that: http://jsfiddle.net/py3DE/203/ but when element is dragged into proper container, we can override it by dragging other div into its area. Could you tel me how i can block dragged elements, and if someone will try to override any element, div returns back into area with undragged divs?
if (!ui.draggable.closest('.empty').length) item = item.draggable()'
There is a simple way to do this. Basically, we'll remove the class empty and use the disable method.
Working Example: http://jsfiddle.net/Twisty/5rdxmp4p/
Minor CSS Change
.filled .item .closer {
display: block;
}
Drop Function
drop: function(ev, ui) {
if ($(this).hasClass("empty")) {
$(this).removeClass("empty").addClass("filled");
$(this).droppable("disable");
} else {
return false;
}
var item = ui.draggable;
if (!ui.draggable.closest('.empty').length) item = item.draggable(); // if item was dragged from the source list - clone it
this.innerHTML = ''; // clean the placeholder
item.css({
top: 0,
left: 0
}).appendTo(this); // append item to placeholder
}
Swapping the class allows the X button to appear. We then run the disable method to ensure that this specific item will no longer accept a dragged item. If the user drags an item to this spot, it is then reverted.
Update
Using Sortable: http://jsfiddle.net/Twisty/5rdxmp4p/2/
HTML
<div id="dragItems" class="source">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
</div>
<div id="sortItems" class="target">
</div>
CSS
body {
background: #fff;
}
.source,
.target {
margin: 20px;
min-height: 190px;
width: 400px;
border: 1px solid green;
}
.target {
border: 1px solid blue;
}
.item {
height: 20px;
margin: 5px;
padding: 5px;
border: 1px solid gray;
background-color: #cd8;
position: relative;
}
.closer {
float: right;
width: 20px;
height: 20px;
border: 0;
background-color: transparent;
}
.closer:hover {
background-color: transparent;
border: 0;
}
.empty {
height: 30px;
margin: 5px;
background: #eee;
border: 1px dashed #999;
}
.highlight {
border: 1px solid red;
background: #fff;
}
.highlight .item {
opacity: 0.3;
}
.ui-draggable-dragging {
z-index: 99;
opacity: 1 !important;
width: 378px;
}
jQuery
$(function() {
$("#sortItems").sortable({
axis: "y",
items: "> div",
placeholder: "empty",
dropOnEmpty: true,
stop: function(e, ui) {
var $it = ui.item;
if ($it.find(".closer").length == 0) {
var closeBtn = $("<span>", {
class: "closer"
});
$it.append(closeBtn);
closeBtn.button({
icon: "ui-icon-close",
label: "Close",
showLabel: false
}).click(function(ev) {
console.log("[INFO]: Closing ", $it);
$it.fadeTo(200, 0.0, function() {
$it.remove();
$("#sortItems").sortable("refresh");
});
});
}
}
});
$("#dragItems .item").draggable({
connectToSortable: "#sortItems",
revert: "invalid"
});
$("#sortItems").disableSelection();
});
I have this setup. JSFiddle link.
$('.item').draggable({
helper: 'clone',
connectToSortable: '.first-sortable, .second-sortable',
});
$('.first-sortable').sortable({
connectWith: '.second-sortable',
receive: function () {
$('.logger1').addClass('animated');
setTimeout(function () {
$('.logger1').removeClass('animated');
}, 300);
}
});
$('.second-sortable').sortable({
connectWith: '.first-sortable',
receive: function () {
$('.logger2').addClass('animated');
setTimeout(function () {
$('.logger2').removeClass('animated');
}, 300);
}
});
.item {
width: 50px;
height: 50px;
background: red;
display: inline-block;
margin-right: 5px;
}
.container {
position: relative;
margin-bottom: 20px;
}
.first-sortable {
height: 100px;
background: blue;
}
.second-sortable {
position: absolute;
left: 50%;
width: 200px;
transform: translateX(-50%);
top: 0;
bottom: 0;
background: rgba(3, 3, 3, .8);
z-index: 10;
padding-left: 20px;
}
.logger2,
.logger1 {
transition: all .3s color;
}
.animated {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div class="container">
<div class="first-sortable"></div>
<div class="second-sortable"></div>
</div>
<div class="item"></div>
<div class="logger1">Blue Sortable Receive</div>
<div class="logger2">Dark Sortable Receive</div>
The main idea is that, as you can see, is that the dark sortable is above the first one, it is positioned using position: absolute and z-index. I have a little bit of opacity for the black one, just so I can look what happens with the first sortable.
Below the bottom red square we have two indicators that shows when receive event is fired on the specific sortable.
Please note the fact that when you drop an item onto the blue sortable, only indicator for this sortable is fired. When I drop a new item onto the black a receive event is fired on both sortables.
Is this behavior a desired one? I think, in this case just the dark one have to receive this event.
I wonder if this is not jQuery UI bug. Ticket.
If a jQuery UI draggable element (#box1) is dragged over an element (#box2) that has z-index set to -1 or below, mouseover and mouseout events won't fire. With z-index set to 0 or above they fire.
CSS:
#box1 {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
border: 1px solid blue;
}
#box2 {
position: absolute;
top: 100px;
left: 300px;
width: 100px;
height: 100px;
border: 1px solid red;
z-index: -1;
}
JavaScript:
$(function() {
$("#box1").draggable();
$("#box2").mouseover(function(e) {
$("#box2").css({
backgroundColor: "green"
});
});
$("#box2").mouseout(function(e) {
$("#box2").css({
backgroundColor: "transparent"
});
});
});
See: http://jsfiddle.net/TTwPj/11/
Without dragging mouseover and mouseout work fine with all z-index-values.
Is there a reason for this behaviour or is it a bug?
This "problem" has nothing todo with negative or positiv values of your z-index.
In this updated fiddle: http://jsfiddle.net/TTwPj/23/
#box1 {
z-index: 2;
}
#box2 {
z-index: 1;
}
you can see I set some positive values and the mousover still not firing. This is how z-index work.
If you want to achive a mouseover while dragging over the droppable element you can use the droppable event:
over: function( event, ui ) {}
to add a CSS class or style to show some visible "mouseover" effect.
I added a jQuery UI accordion here: http://www.letmagichappen.com/web_resources to accommodate a large amount of data. The accordion works fine, but the size of the content area is much larger than needed for the content.
I reviewed the css:
.web_resources .ui-accordion { width: 100%; }
.web_resources .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.web_resources .ui-accordion .ui-accordion-li-fix { display: inline; }
.web_resources .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.web_resources .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.web_resources .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.web_resources .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.web_resources .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.web_resources .ui-accordion .ui-accordion-content-active { display: block; }
The HTML is pretty straight forward:
<h4>Chapter 1</h4>
<div>
<p>Rotator Cuff Tears: Prospective Comparison of MR Imaging with Arthrography, Sonography, and Surgery</p>
<p>Magnetic Resonance Imaging of the Lumbar Spine in People without Back Pain</p>
<p>1.5 Tesla Surface Coil MRI of the Knee</p>
<p>Yoga Research Society</p>
<p>Radiological Society of North America</p>
<p>Sample 1</p>
</div>
Here is the code for the Accordion:
<script type="text/javascript">
$(function(){
$(".web_resources").accordion({ header: "h4" });
});
</script>
I would appreciate some insights into what is causing the content area to display so big and how to bring it under control.
Thanks!
This was much simpler than I thought. By default Accordion "auto-heights" to the largest div. To change that requires to set it to:
autoHeight: false