Is there any way that I can "Stack" the jQuery UI Tabs Header? Please allow me to explain: I have tabs which may require two or more words for the titles to be self-explanatory. For instance:
"PDP Undeveloped"
My problem is that I am running out of space when adding a bunch of tabs. So instead of writing the tab as
PDP Undeveloped
I would like it to show as
PDP
Undeveloped
Is that possible? If not then are there alternate ways of solving this problem?
Thanks in advance.
Bharat
I would recommend using <br /> tags. Since you only want them to take effect when you're short on space I'd recommend using media queries to turn on the multi line display.
<div id="tabs">
<ul>
<li>Nunc <br />tincidunt</li>
<li>Proin <br />dolor</li>
<li>Aenean <br />lacinia</li>
</ul>
<div id="tabs-1">Tab 1</div>
<div id="tabs-2">Tab 2</div>
<div id="tabs-3">Tab 3</div>
</div>
<style>
br { display: none; }
/* Replace 700px with whatever width you want the multi line display to start */
#media screen and (max-width: 700px) {
.ui-tabs li { height: 4em; }
br { display: inline; }
}
</style>
Live example: http://jsfiddle.net/vvpeF/
Related
I'm setting up my first ever ASP.NET MVC server and teaching myself how to use it for a particular project I'm working on.
I have a couple of controller "endpoints" set up and working wonderfully for HTTP POST requests but, as a "tangential" part of this project, I would like to have the controller serve up a page with a file upload form.
Specifically, I'd really like to use the Vue File Agent, preferably implemented using the CDN distribution method because I'd rather not install additional components on the server for this one little thing if I can get away with it.
I'm not new to ASP.NET, HTML, or CSS (and even limited JavaScript), but I am unfamiliar with using ASP.NET MVC controllers and views to serve page(s). As stated, I've figured out how to use the controllers to handle the POST requests I'm generating from other systems.
Also, I have a "basic" understanding of how the view works and I've got the controller serving up an HTML file. However, when I try to include the Vue File Agent component via the CDN, I'm not getting anything.
I've tried a variety of different Vue File Agent samples just to get something on the page, including the Gmail Inspired Demo on CodePen, but I must be missing something because I can't get the actual "sample" to show up and it seems to be totally ignoring all of the CSS styling.
In my controller, I have this:
Function Index() As ActionResult
Return View()
End Function
And my Index.vbhtml file looks like this:
#Code
Layout = Nothing
End Code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Insurance Submission Form</title>
<link rel="stylesheet" href="https://unpkg.com/vue-file-agent#latest/dist/vue-file-agent.css" />
<script src="https://unpkg.com/vue-file-agent#latest/dist/vue-file-agent.umd.js"></script>
<style>
.vfa-demo {
position: relative;
}
.vfa-demo .file-preview-wrapper::before {
background: transparent;
}
.vfa-demo .file-row {
position: relative;
z-index: 15;
line-height: 24px;
text-align: left;
background: #EEE;
margin-bottom: 5px;
padding: 2px 5px;
}
.vfa-demo .remove {
float: right;
margin-top: -3px;
}
.vfa-demo .progress {
float: right;
width: 85px;
height: 10px;
margin-top: 7px;
margin-right: 10px;
background: #FFF;
border: 1px solid #AAA;
}
.vfa-demo .progress.completed {
display: none;
}
.vfa-demo .drop-help-text {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: 2px;
background: rgba(255, 255, 255, 0.75);
z-index: 1200;
font-size: 32px;
font-weight: bold;
color: #888;
align-items: center;
justify-content: center;
display: none;
}
.vfa-demo .is-drag-over .drop-help-text {
display: flex;
}
.vfa-demo .upload-block {
border: 2px dashed transparent;
padding: 20px;
padding-top: 0;
}
.vfa-demo .is-drag-over.upload-block {
border-color: #AAA;
}
.vfa-demo .vue-file-agent {
border: 0 !important;
box-shadow: none !important;
}
</style>
</head>
<body>
<script type="text/x-template" id="vue-file-agent-demo">
<div class="vfa-demo bg-light pt-3">
<VueFileAgent class="upload-block"
ref="vfaDemoRef"
:uploadUrl="'https://www.mocky.io/v2/5d4fb20b3000005c111099e3'"
:uploadHeaders="{}"
:multiple="true"
:deletable="true"
:theme="'list'"
:maxSize="'25MB'"
:errorText="{
size: 'This file is too large to be attached',
}"
v-model="fileRecords">
<template v-slot:before-outer>
<p>Email Attachment example with drag & drop support and <span class="badge">attachment</span> keyword basic detection.</p>
<div class="form-group">
<input type="text" class="form-control" placeholder="Your Name" value="John Doe">
</div>
<div class="form-group">
<input type="email" class="form-control" placeholder="Email address" value="johndoe#example.com">
</div>
<div class="form-group">
<textarea v-model="message" class="form-control" placeholder="Your Message"></textarea>
</div>
</template>
<template v-slot:file-preview="slotProps">
<div :key="slotProps.index" class="grid-box-item file-row">
<button type="button" class="close remove" aria-label="Remove" v-on:click="removeFileRecord(slotProps.fileRecord)">
<span aria-hidden="true">×</span>
</button>
<div class="progress" :class="{'completed': slotProps.fileRecord.progress() == 100}">
<div class="progress-bar" role="progressbar" :style="{width: slotProps.fileRecord.progress() + '%'}"></div>
</div>
<strong>{{ slotProps.fileRecord.name() }}</strong> <span class="text-muted">({{ slotProps.fileRecord.size() }})</span>
</div>
</template>
<template v-slot:file-preview-new>
<div class="text-left my-3" key="new">
Select files or drag & drop here
</div>
</template>
<!-- <template v-slot:after-inner>
<div class="text-left pt-1">
Select files or drag & drop here
</div>
</template > -->
<template v-slot:after-outer>
<div title="after-outer">
<div class="drop-help-text">
<p>Drop here</p>
</div>
<button type="button" class="btn btn-primary" v-on:click="send()">Send</button>
</div>
</template>
</VueFileAgent>
</div>
</script>
<!-- ----------------------------- -->
<div class="container py-3">
<div id="app">
<h5><a target="_blank" href="https://safrazik.github.io/vue-file-agent">Vue File Agent</a> Playground</h5>
<hr>
<ul class="nav nav-pills mb-2">
<li class="nav-item">
<a target="_blank" class="nav-link" href="https://codepen.io/safrazik/pen/BaBVNEE">1. Preloading Exising Demo</a>
</li>
<li class="nav-item">
<a target="_blank" class="nav-link" href="https://codepen.io/safrazik/pen/BaBpYme">2. Profile Picture Demo</a>
</li>
<li class="nav-item">
<a target="_blank" class="nav-link active" href="https://codepen.io/safrazik/pen/OJLgvya">3. Gmail Inspired Demo</a>
</li>
</ul>
<hr>
<vue-file-agent-demo></vue-file-agent-demo>
</div>
</div>
<script type="text/javascript">
var component = {
data: function () {
return {
fileRecords: [],
message: 'I am sending you the attachments',
}
},
methods: {
removeFileRecord: function (fileRecord) {
return this.$refs.vfaDemoRef.removeFileRecord(fileRecord);
},
send: function () {
if (this.message.indexOf('attachment') !== -1 && this.fileRecords.length < 1) {
if (!confirm('You have mentioned about attachments in your message. Are you sure to send without attachments?')) {
return;
}
}
alert('Message sent!');
}
}
}
component.template = '#vue-file-agent-demo';
Vue.component('vue-file-agent-demo', component);
new Vue({
el: '#app'
});
</script>
</body>
</html>
I tried using various other different upload "templates" I've found with varying degrees of success, but I feel I'm still failing to understand some key concepts of working with ASP.NET MVC controllers and views.
For one thing, in the <template v-slot:file-preview="slotProps"> and <template v-slot:after-outer> blocks of the code above, the CodePen has the <button> elements defined with #click="somefunctionname()".
However, when I publish these, the server returns an error indicating that 'click' is not declared (IntelliSense also reports the same error in the Visual Studio IDE). I found some other examples using Vue that showed what appears to be the same basic functionality written as v-on:click="somefunctionname()", so I tried that (as I have listed above), but I'm still getting nothing.
I'm obviously not understanding how the syntax should be working here, and I'm sure it's "simply" a matter of finding the right documentation, but I'd really like to understand the ASP.NET MVC view a little better and figure this out, not only because I want to get this "pretty" upload working, but because I really want to get a better handle on how to use this technology.
What is it that I'm doing wrong and how can I get this functionality working on my ASP.NET MVC controller? How do I define these # directives in an ASP.NET MVC view without causing the compiler to freak out (I had the same issue with some of these # directives in a CSS <style> block, so it's clearly something I'm going to need to deal with)?
EDIT
So, as I sorta mentioned above, I've been testing by publishing the site to my web server and viewing the site via the public DNS name. Just to see if I would get anything different, I tried running the site from the Visual Studio debugger.
Interestingly, when I did this, the IDE broke with an exception in my _Layout.vbhtml:
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required:=False)
Looking at my site's directory structure, there is no ~\bundles\ directory. Digging around a little, I found all of the jQuery and Bootstrap files located in the ~\Scripts\ directory, so I simply removed the two calls to the #Scripts.Render() method (leaving the call to #RenderSection()) and tried again. This time, I didn't get the exception, so I went ahead and published again to test. Unfortunately, I got the same results as what I posted in my screenshot, so that doesn't appear to be the source of my "issue", but I thought I'd mention it here, just in case it helps to point me in the right direction.
As I said at the beginning of my question, this is my first time setting up an ASP.NET MVC server, so I've not done much in the way of customization or modification to the base template from Visual Studio apart from creating a new controller and associated view and adding a couple of things to the web.config / global.asax to handle some of the other functionality I'm implementing. Perhaps there's something I should have done, but I don't really know where to start.
Well, I finally figured out at least part of my problem, and it's because I'm a moron. I stumbled across it when I opened up my browser's "Developer Tools" and drilled down through a few screens. Apparently, I was missing a pretty important piece of the Vue puzzle in my HTML. Once I added this line to my <head> (the "core" Vue library):
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.12/dist/vue.js"></script>
I finally got a visible upload box. It's still missing all the nice-looking styling, but at least the control is there now and I can start working with it a little more.
I put my footer on the last row of an col-md-12 container and expect the footer to be the same width as the col-md-12 container. Instead of this it starts corretly on the left side with the container, but on the right side it ends at the display border and not at the container.
<html>
<head>
<title>footertest</title>
<!-- bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<style>
.myleft{
width: 100%;
background-color: rgb(227, 236, 97);
height: 400px;
}
.myright{
width: 100%;
background-color: rgb(19, 197, 49);
min-height:100%;
}
.mytest{
width: 100%;
background-color: aqua;
height:50px;
position:fixed;
bottom:0;
}
</style>
</head>
<body>
<div class="container">
<div class="row " > <!-- arbeitsbereich links + rechts- -->
<div class="col-md-6 myleft"> <!-- linke Haelfte -->
this is the left side (col-md-6)
</div>
<div class="col-md-6 myright" > <!-- test1 hat den style lightblue im css-->
<!-- rechte Haelfte-->
this is the right side (col-md-6)
</div>
</div>
<div class="row " >
<div class="col-md-12 mytest">
this is my footer. It starts correctly at the left side of the container, but ends at the right site of the display instead of the container
</div>
</div>
</div>
</body>
</html>
here is a screenshot of the result:
https://zaunraum.de//IsMobileTest/footer.jpg
It's because width of a fixed position is not relative to the place where it's displayed (it's like if you place this element with position absolute)
the element is displayed out of container and don't take into consideration width of col-md-12
like you put 100% width to class .mytestin, this one will take width of entire page
you have different way to fixed your issue :
put a max-width on your footer
put a margin on page
but in all cases you have to considered your element as a standalone one
I solved the problem by creating the footer as a standalone element (as suggested by jeremy-denis) and then inserting a col-md-12 container into the footer. This then behaves natrlih exactly like the main container.
Thanks for the help.
I'm trying to apply this SlickGrid example:
http://mleibman.github.com/SlickGrid/examples/example4-model.html
to my own web project.
When I drop my grid in to the top of my page, it renders correctly. However, when I drop it into a jQuery UI Tabs tab on the same page, the CSS Sprite that renders the search image is incorrectly offset.
The icon is rendered with
<span title="Toggle search panel" class="ui-icon ui-icon-search ui-state-default ui-corner-all" style="float: right;" onclick="toggleFilterRow11()"/>
It looks like jQuery UI Tabs also uses the same CSS classes, and of course a conflict arises.
Looking at the effective styles in IE9, the control outside of jQuery UI Tabs that renders correctly has the following:
The control that renders incorrectly looks like this:
Bottom Line
Placing the SlickGrid in a jQueryUI Tab causes the ui-icon-search class to be lost and therefore the wrong background-position-x/y to be set.
Why is that class being lost and how can I fix the issue?
The problem
When jQueryUI creates tabs from the HTML it adds the jQueryUI CSS classes. From the jQueryUI examples:
<div id="tabs">
<ul>
<li>Nunc tincidunt</li>
<li>Proin dolor</li>
<li>Aenean lacinia</li>
</ul>
<div id="tabs-1"></div>
<div id="tabs-2"></div>
<div id="tabs-3"></div>
</div>
becomes
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active">Nunc tincidunt</li>
<li class="ui-state-default ui-corner-top">Proin dolor</li>
<li class="ui-state-default ui-corner-top">Aenean lacinia</li>
</ul>
<div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom"></div>
<div id="tabs-2" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
<div id="tabs-3" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
</div>
The problem is happening because the SlickGrid content now exits as a child of an element with the class ui-widget-content. Actually, there are 2 ancestors of the grid header that have that class - in the above code see <div id="tabs"> and <div id="tabs-1"> both have that class applied when tabs are created.
The jQueryUI CSS rules that are supposed to apply to get the correct search icon are:
.ui-icon {
width: 16px;
height: 16px;
background-image: url(images/ui-icons_222222_256x240.png);
}
.ui-icon-search {
background-position: -160px -112px;
}
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
border: 1px solid #d3d3d3;
background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;
font-weight: normal;
color: #555555;
}
The markup for the icon is:
<span style="float:right" class="ui-icon ui-icon-search ui-state-default ui-corner-all" title="Toggle search panel" onclick="toggleFilterRow()"></span>
so therefore the CSS rules .ui-icon, .ui-icon-search and the first match of the 3rd rule .ui-state-default are applied.
However when the same markup exists as a descendent of a element with the class .ui-widget-content, the 2nd part of the 3rd rule above (.ui-widget-content .ui-state-default) also matches which is more specific. See http://www.stuffandnonsense.co.uk/archives/images/specificitywars-05v2.jpg for a Star Wars themed explaination of CSS specificity. Essentially the background property of the 3rd rule that includes background-position:50% 50% is more specific than the single selector .ui-icon-search rule therefore overriding the correct background-position:-160px -112px.
The solution
Need to make the .ui-icon-search rule the same or more specific than the .ui-widget-content .ui-state-default rule which can be done by either:
Adding !important to the rule
Adding more selectors to the rule
For example
.ui-icon-search {
background-position: -160px -112px !important;
}
or
.ui-icon-search, .ui-widget-content .ui-icon-search {
background-position: -160px -112px;
}
I cannot think of a way that doesn't involve changing the jQueryUI CSS (or duplicating the .ui-icon-search rule in your own CSS with one of the two solutions above). I would actually be interested to see if there is another way myself!
I'm using jQueryUI Tabs and have a requirement to add UI elements to each tab that allow a user to Edit information about the tab, or remove the tab.
The markup I use on the <li> for a given tab looks like this:
<li>
<div style="background-color:Red;"> <-- Red to see what's happening -->
<span>Tab One</span>
<div style="text-align:right; margin-right:3px;">
<div><span id="editTab-1">edit</span></div>
<div><span id="delTab-1">X</span></div>
</div>
</div>
</li>
This renders just as I would hope in IE
______________________________
| Edit|
| Tab One |
|___________________________X__|
but it does not render properly in Chrome or FireFox (the tab is only wide enough for the "Tab One" text, and "Edit" / "X" are mostly "under" the tab (lower Z-Index apparently).
What is a compatible way to achieve my goal?
I'm not sure if this is what you were intending or not, as I haven't tested in IE, but this works in Chrome and FF:
<div id="tabs">
<ul style="cursor:pointer">
<li>
<a href="#tabs-1">
<div style="float: left; margin-right: 20px;">Tab One</div>
<div style="float: right; text-align:right;">
<div id="editTab-1">edit</div>
<div id="delTab-1">X</div>
</div>
</a>
</li>
<li>
<a href="#tabs-2">
<div style="float: left; margin-right: 20px;">Tab Two</div>
<div style="float: right; text-align:right;">
<div id="editTab-2">edit</div>
<div id="delTab-2">X</div>
</div>
</a>
</li>
</ul>
<div id="tabs-1" class="tabPane">Tab One Content</div>
<div id="tabs-2" class="tabPane">Tab Two Content</div>
</div>
See the working jsFiddle
If you want to handle the clicks dynamically, you could use:
var $tabs = $("#tabs").tabs();
$tabs.find("a div[id]").on("click", function() {
var id = $(this).attr("id"),
idTab = parseInt(id.substring(id.length - 1)),
isEdit = id.indexOf("edit") > -1,
isDelete = id.indexOf("del") > -1,
index = $tabs.tabs('option', 'selected');
if (index + 1 === idTab) {
if (isEdit) {
console.log("Edit Tab " + (index+1));
//however you want to edit here
}
if (isDelete) {
console.log("Delete Tab " + (index+1));
$tabs.tabs("remove", index);
}
}
}).css("cursor", "pointer");
See the working jsFiddle
The problem, I think, stems from the fact that the tab <li> and then the <a> inside are floating elements, as designed in the jQueryUI CSS.
The technical part can best be summed up with this quote (from http://css.maxdesign.com.au/floatutorial/introduction.htm)
If no width is set, the results can be unpredictable. Theoretically, a floated element with an undefined width should shrink to the widest element within it. This could be a word, a sentence or even a single character - and results can vary from browser to browser.
So the red <div> is shrinking to the widest element - the <a>. IE and Firefox/Chrome are simply behaving differently, just their interpretation of the specifications. To be honest, that fact that Firefox and Chrome are similar and IE has had a long history of float bugs I'd side with Mozilla/Google here although can appreciate that IE seems to be behaving nicer in this instance.
You can solve the problem by simply setting a width on the red <div>. However the markup could also be a bit cleaner, for example:
<li style="background-color:red;width:150px">
Tab One
<div id="editTab-1" style="text-align:right;margin-right:3px">edit
<p id="delTab-1">X</p>
</div>
</li>
gives the same result.
I am using a jquery accordion with just one content panel like so:
<ul id="myaccordion">
<li>
Header Title
<div>
Content in here.
</div>
</li>
</ul>
and then calling:
$('#myaccordion').accordion();
The problem I'm having is that the content part of the accrodion id the correct width, but the header is merely the width of the text that says 'Header Title' and this text is overlapping the arrow icon.
Can anyone see why the header wouldn't be the same width as my content? I have tried setting a specific with to the ul, the li and the a tags, but to no effect.
Many thanks in advance.
The accordion code expects a header around that anchor for styling (or any wrapper element really), since this styling here needs it:
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
Just add a wrapper in there, like this:
<ul id="myaccordion">
<li>
<h3>Header Title</h3>
<div>
Content in here.
</div>
</li>
</ul>
Here's a demo showing both with and without the <h3>, so you can see the effect.