Some areas inside the Vuetify Dialog box don't close it even if there is no content there - vue.js

See this image here of my custom Lightbox component.
One should be able to simply exit the component and go back to the page by clicking on anywhere outside the image or the v-sheet component on the right (which by the way, is supposed to be touching the image, but I can't figure out how to move it without using margin).
Unfortunately, the red boxes exist - they are areas where clicking should close the dialog, but don't. This is because the entire Dialog component is the green box - it believes even those red boxed areas are part of the component.
I've been attempting to use #click and v-click-outside directives where possible to try and exclude the image and the sheet component can be clicked but everything else closes the dialog, but unfortunately I only get strange behaviors that donn't help at all.
Also, I found out using margin: auto will create another unclickable area, so I need to find out another way to move it over.
Source Code

Problem 1:
"is supposed to be touching the image, but I can't figure out how to move it without using margin"
Instead of lg="10" on the first col, you can use lg="auto" so it will shrink to fit its contents.
justify="center"
class="fill-height"
>
<v-col
- lg="10"
+ lg="auto"
md="12"
offset-lg="0"
class="fill-height text-right"
>
Problem 2:
"areas where clicking should close the dialog, but don't"
You can use pointer-events: none on the dialog body to disable click event capturing, then pointer-events: auto on specific elements to selectively enable it.
<v-col
lg="2"
md="4"
align-self="top"
- #click="dialog = false"
>
<v-sheet
class="rounded-tr-lg text-left"
...
- <style lang="scss">
- .v-dialog {
+ <style lang="scss" scoped>
+ ::v-deep .v-dialog {
margin: 0;
padding-left: 24px;
padding-right: 24px;
box-shadow: none !important;
+ pointer-events: none;
+ }
+ .v-image,
+ .v-btn,
+ .v-sheet {
+ pointer-events: auto;
}
</style>

Option 1: Use flexbox and #click function to close whatever
Basically, if you get your css to do a similar layout, but fill those red boxes with a background: blue you in turn can put an #click on that same div, which will close whatever you need.
Option 2: Use Modals
I would use a parent component that communicates to an "image component" and "image details component" (such that the two components are siblings.
Moreover, I would personally use v--modal for both of these sibling components, and have the closed event tied to a single instance of closing both modals by names
The shiftX and shiftY should be enough for placement.
https://www.npmjs.com/package/vue-js-modal

Related

How to style Grid cell/row background without using classname generator

I searched a lot, but every solution was to include some constant CSS class names into the page, and use the Column's ClassNameGenerator to set the proper classname on the cell/row.
Now this might be a good solution when the developer can decide on formatting a cell, however when a user can decide (especially with a script written as cell renderer) how a cell will look like, it is not possible to use the ClassNameGenerator.
So question is, how can I format the cell/row background programmatically, not using any CSS? I can provide custom component as cell value. So it's fine to render a label with icon, or just icon, or a checkbox, however coloring this rendered component is not enough, since this is smaller than the cell itself, making it look really ugly. I need to access the root element of the cell, and color it using getStyle().set("background", "xxxx"). How to achieve this?
Thanks!
You can use a TemplateRenderer.
For example:
Grid<Person> grid = new Grid<>();
grid.setItems(people);
grid.addColumn(TemplateRenderer
.<Person>of("<b>[[item.name]]</b>")
.withProperty("name", Person::getName)
).setHeader("Name");
Checkout this tutorial for more information: https://vaadin.com/docs/v14/flow/components/tutorial-flow-grid
OK, finally I solved. I use a template renderer with a proper template structure. I modified the cell style in a way, that my renderer DIV fills the entire cell (removed any padding/margin from the original cells)
<dom-module id="grid-style" theme-for="vaadin-grid">
<template>
<style>
[part~='cell'] ::slotted(vaadin-grid-cell-content) {
padding: 0px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
--cellopa: 255;
}
[part~='cell'][aria-selected~="true"] ::slotted(vaadin-grid-cell-content) {
--cellopa: 0;
}
</style>
</template>
</dom-module>
I also added some simple CSS declarations to one of the main CSS:
vaadin-grid-tree-toggle flow-component-renderer {
width: 100%;
height: 100%;
}
vaadin-grid-cell-content flow-component-renderer {
width: 100%;
height: 100%;
flex-grow: 1;
}
This way the rendered DIV fills the whole cell and I can color it's background.
Now the problem comes with the selection, since the selection is not visible any more. For this you find the --cellopa variable set to 255 normally and set to 0 for selected cells.
Now when I define a background-color on the div, I use rgba and I set the alpha to the var(--cellopa) variable, like this for example rgba(255, 0, 0, var(--cellopa))
Now when the row is not selected, the cellopa is 255, so the background is visible, when I select the row the cellopa is set to 0, so the background of the DIV gets transparent, and the row selection color on the row is visible. This is super fast, and changing the selection does not cause any glitch, and also the previous coloring state is restored properly.
I also managed to get around with the treegrid and managed to color even the hierarchy column fully using a special template for the hierarchy column with some padding taking the level into account.

VUEJS Set autofocus to ALL user inputs when component is created

I need to focus all the form user inputs onCreate(), so to make clear to the user that he can edit the fields if he needs to.
The closer thing I found is something like:
<input ref="email" />
const input = this.$refs.email
methods: {
focusInput() {
this.$refs.email.focus();
}
That should work, but I was looking for a better way to do it, without applying the ref attribute to every single input.
Is there a way to wrap them all at once?
I tried attaching the ref to the form <b-form ref="focusInputs">, then, in the method, access the inputs through it
focusInputs() {
this.$refs.focusInputs.input.focus();
}
and call it in created:
created(){
this.focusInputs()
}
But in the console I got:
Error in created hook: "TypeError: Cannot read property 'input' of undefined"
I think that's because I am using bootstrap-vue, so the input tags are <b-form> and <b-form-input> (instead of just <form> and <input>). CSS and Javascript, as far as I know, are not able to access these tags as the can with form or input.
So, do you think is there still a way to wrap them all, or do I need to mark them singularly (either with a class or with ref).
Anyone know?
Thank you,
x
You can create a css class that will apply the bootstrap textbox highlight color to any textboxes you want. The below CSS should do the trick. You can find this CSS in the bootstrap files, I just changed the name and removed the focus requirement.
You cannot however actually "Focus" multiple fields since focus is where the input cursor is set. You can only auto focus one field at a time.
.fillable{
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
}

Ionic4 Print Media Query for Scrollable ion-content

Pretty straightforward problem. Have scroll-able ion-content in my Ionic4 application. I want to be able to print it gracefully by applying #media only print styles. I'm almost there, but I have one major problem. I cannot get the vertical scrollbar to disappear for printing. Additionally, I only ever get one page printed, containing only the content that is in view when I print the page. I've scoured the web for solutions, and come across and tried various suggestions in the context of Ionic3 and earlier, but I haven't found the magic bullet for Ionic4 yet. Has anyone encountered and gotten to the bottom of this yet?
I have been through the ringer on trying to print content in Ionic 4. Some of the steps i followed to print multiple pages.
remove any flex-box styled lists. They just will not print how you want them to across pages, though they have worked fine for me if the content fits in a page.
for items you want to be seperated by page, its best if they are a display: block; styled item, so that that in the print style sheet you can use one of the page-break properties on it
on the item containing your list, the ion-content for example, make sure you remove any max-height attributes from it or any of its ancestor or child elements, as well as removing the overflow: scroll from these elements as well so that it allows your content to go from page to page. for example on my stylesheet for printing (cant share it because of NDAs) I had a lot of overflow-y: visible on elements just to make sure it shows. if you find an element thats cutting off your html, it should be the primary target for experimentation.
you can simulate a print in the dev tools, i found it useful, it's good for iteration here's a link
some other things that may help, but i am not sure as I did so much testing across browsers, and only vaguely remember what impact that css property had is to have the body with a static position, as well as having contain: none on the body to say that the browser should render as normal, little more explanation here
i do not know the specifics of your use case, but if you don't mind foregoing the native print button, and just giving the user a button to click to trigger the print, then that would be more manageable as you do not have to account for all the scaffolding around that specific element that you want to print (the ion-router, ion-page, and all the ancestors)
If you did that then you could put all your items you want to print into a div with an id of printSection or what you prefer, and then the javascript that is responsible for that page you can create your own print function. In my example i will use angular, if you are not using that then preform whatever DOM selecting you need to to get the native html out of your template.
#Component({ ... })
export class Page {
// select the item holding your print content by `#property` you gave it
#ViewChild('printSection', { read: ElementRef }) printSection: ElementRef;
...
customPrint() {
const printContent = this.printSection.nativeElement;
const WindowPrt = window.open('', '', 'left=0,top=0,width=900,height=900,toolbar=0,scrollbars=0,status=0');
WindowPrt.document.write(printContent.innerHTML); // pass in the native html you got
/**
* you should probably use an observable instead of an interval for this,
* but this is just to illustrate a bug where the print would be fired before
* all the content was written
*/
const interval = setInterval(
() => {
if (document.readyState === 'complete') {
WindowPrt.document.close();
WindowPrt.focus();
WindowPrt.print();
clearInterval(interval);
}
},
200);
}
}
I Solved it following this process
First, remove the content to be printed from ion-content. Use a div instead of ion-content(shadow-dom is implemented with ion-content which blocks your CSS classes)
You also need to force the CSS below on ion-page when printing (it is initially set to position: absolute, by default)
In my case I was printing from a modal component which has a default class "show-modal". I was able to print on multiple pages by target that class this way
#media print {
.ion-page {
left: 0;
right: 0;
top: 0;
bottom: 0;
display: block;
position: relative;
flex-direction: column;
justify-content: space-between;
contain: none;
overflow: visible;
z-index: 0;
}
.scroll-content,
ion-modal.show-modal,
ion-modal.show-modal .modal-wrapper,
ion-modal.show-modal .ion-page.show-modal,
ion-modal.show-modal .ion-page.show-modal > ion-content,
.ion-page.show-modal,
.ion-page.show-modal > ion-content,
ion-tab,
ion-tabs,
.app-root,
body {
contain: none;
position: relative !important;
height: auto;
overflow: visible;
}
}
I'm also trying to solve this same issue. I've scoured the Internet, and tried many an idea, but none has worked so far.
Perhaps we could solve this collaboratively. I'd put this as a comment, but I don't have enough rating points, so the system will not let me.
This is what I've found so far. In Chrome Developer Tools, you can click on a settings icon, then scroll to "Rendering," and on "Emulate CSS media type," select "print."
When I do that, it shows what the print view is. I created a separate css file, let's call it print.css, and in it, there is
#media print {
/* add your css styles for print here */
}
I know my print.css is being processed because I've
display: none
for ion-header and some tabs at the bottom, and they do disappear when I select "print" emulation in Chrome.
What is interesting is, I'm seeing the whole page -- scrollable and all -- on the screen in this print mode. However, every time I try to print it, only one page shows up.
That page, however, doesn't always start at the top. It includes the current viewport.
Which is why, I'm wondering if there is something in the css that is trying to keep the whole thing as a page. i.e., preventing a page break?
I'm experimenting with things like this:
ion-content, .foo, .bar, ion-list, ion-tabs, ion-item {
break-inside : auto !important;
break-after : auto !important;
break-before : auto !important;
}
(where foo and bar are classes you might have of your own.)
This above one breaks things. Removing ion-tabs, ion-list, and ion-item shows the full page.
I'm also experimenting with the following. None has worked so far, but that is probably because I haven't selected the right tag or class.
display: block !important;
height: 100%;
overflow-y: visible !important;
max-height: unset !important;
contain: none;
You may want to experiment with the tag in question that might be preventing a page break. Some people are suggesting it's flexbox or grid that's the root cause. I'd love to know how to find the root cause.
Good luck! If something works, let us know, so I'll also try it in my code.

Safari a:hover changing sibling in fixed element

I am making a simple fixed SoMe sharing button set for a blog. Everything is fine and dandy except in Safari. Hovering over one of the buttons changes the background-color of the siblings to a color I do not specify anywhere in my CSS. This behavior goes away as soon as I change the wrapper from fixed to relative/static/absolute.
Has anyone ever run into this?
Am I doing something wrong?
If not, is there a hack/fix/workaround?
HTML:
<div id="share-links">
<a class="share-twitter" href="#">a</a>
<a class="share-facebook"href="#">a</a>
<a class="share-linkedin" href="#">a</a>
</div>
CSS:
#share-links{
left:0;
top:5em;
position:fixed;
}
#share-links a{
display:block;
height:2em;
width:2em;
color:white;
background-color:#a16159;
}
#share-links a:hover{
background-color:#8a392e;
}
Fiddle: https://jsfiddle.net/u6vzq192/26/
I discovered this problem in a slightly different situation. I have pagination dots in a fixed div using links like you have set up. I am adding a class to the links with Javascript which in turn changes the background color. Every time this happens the background colors of all the other links go crazy. I believe that it is a rendering bug in Safari inverting the background of the links when one changes.
After much experimentation with your example I discovered that it stops if either the links themselves are much larger or the container is much larger. Since setting the links to be giant buttons affects design, it seems the best solution is to set the container to be larger. Since your example is a vertical set of links you would set the height of the container to be something much larger than the links. I used height: 100%; but a large px should work too. If you had links laid out horizontally you might need to make that width: 100%; instead.
CSS:
#share-links{
left:0;
top:5em;
position:fixed;
height: 100%;
}
#share-links a{
display:block;
height:2em;
width:2em;
color:white;
background-color:#a16159;
}
#share-links a:hover{
background-color:#8a392e;
}
I encountered a similar problem. As well as being fixed, one of the inside elements had transform:rotate 90 deg and had a hover effect that changed its position slightly (pulled out from the side of the screen). The background color of this element and its sibling were the same, and both would flicker randomly when elements on the page were changed / rendered.
I finally found a combination of styles that stopped the background colour flickering altogether.
I added the following to the parent element from here: https://stackoverflow.com/a/27863860/6260201
-webkit-transform:translate3d(0,0,0);
-webkit-transform-style: preserve-3d;
That stopped the flickering of the transformed/sliding element.
And I added the following to the remaining element from here: https://stackoverflow.com/a/19817217/6260201
-webkit-backface-visibility: hidden;
This then stopped the flickering of the background colour for the sibling element.

How to Split Blogger header into 2 columns?

i would like to ask how can i split my blogger header into two columns? Can you help me please? I'm having a hard time figuring out...
btw, i just need to add my logo at the left then google adsense on the right.
Thanks!
first you need to configure your blogger header max widgets. Check it if its more than 2. if not change it to (let's say) 4 and add the following css attributes under the #header & #header2:
float:left;
width:50%;
You'll be able to add new gadgets which is aligned horizontally. then add google adsense on the right and your logo at the left. Save your template and view!
Login to Blogger.com
Click on the "Template" section.
Click on "Jump to Widget"
Click on "Header1"
Under the code it jumps to, ie:
<b:section class='header' id='header' maxwidgets='2' showaddelement='no'>
<b:widget id='Header1' locked='true' title='Your Bog Tittle (Header)' type='Header'>
</b:widget>
</b:section>
Insert this code:
<b:section class='header' id='header2' maxwidgets='2' showaddelement='yes'>
</b:section>
<div style='clear:both;'/>
Now search for and find: "/b:skin"
ABOVE "/b:skin" insert this code:
#header {
float:left;
width:50%;
}
#header2 {
float:right;
width:30%;
}
You can adjust the percentages based on what you desire.
On the layout page, after you save the template AND REFRESH, you should see an "Add a Gadget" area to the right of your logo, where you can insert your adsense widget.
If things don't look right on the Layout page, place these codes below the other ones:
#layout #header, #layout #header2 {
padding: 0px !important;
margin: 0px !important;
width: 50% !important;
}
Remember to save your template and also remember to click REFRESH after you save your template.