Show hidden textbox with Polymer after button press - javascript

I have the following code
<dom-module id="practice-list">
<template>
<paper-drawer-panel>
<paper-header-panel main mode="waterfall-tall">
<paper-toolbar id="mainToolbar">
<paper-icon-button id="paperToggle" icon="menu" paper-drawer-toggle></paper-icon-button>
<span class="flex"></span>
<paper-icon-button icon="search" on-tap="srchandler" id="srchandler"></paper-icon-button>
<input type="text" id="searchText" show$="{{show}}" />
<div class="middle paper-font-display2 app-name ident">Practice List</div>
</paper-toolbar>
</paper-header-panel>
</paper-drawer-panel>
</template>
<script>
Polymer({
is: "practice-list",
show: {
type: Boolean,
value: false
},
ready: function () {
},
srchandler: function () {
this.show = !this.show;
alert('Is it showing?');
}
});
</script>
</dom-module>
Which in turn uses the following css
#searchText
{
width:0px;
border: none;
line-height:30px;
border-radius:5px;
background:#3F59B5;
color:#fff;
outline: 0;
visibility: hidden;
}
#searchText[show] input {
padding: 10px;
visibility: visible;
width:200px;
}
Now I was trying to use the technique described here, but to no avail.
polymer search input text from icon
Even though I know the handler for the on-tap of the paper-icon-button is working and called the textbox does not appear.

Why not use the HTML5 attribute hidden? (see here for more info)
Your input would change to:
<input type="text" id="searchText" hidden$="{{hidden}}" />
Then in your CSS you can remove the visibility rules and the show attribute:
#searchText {
border: none;
line-height: 30px;
border-radius: 5px;
background: #3F59B5;
color: #fff;
outline: 0;
}
#searchText input {
padding: 10px;
width: 200px;
}
And change the property show to be hidden to make the things a bit more logical:
hidden: {
type: Boolean,
value: true
},
Here is a very simple plunker of this in action.

Related

Vuejs - Why does the trigger of a method also trigger an unrelated method via v-if

I have created a component that does two things.
Feature 1: toggling a button cycles between a blue square and a red square.
Feature 2: inputting 5 or more characters in an input area reveals a green square.
<template>
<div id="app">
<div id="container1">
<h2>Container 1</h2>
<h5>Toggle Button to Change Box</h5>
<div class="box1" v-if="isBlueBoxDisplayed()">
<span>1a</span>
</div>
<div class="box2" v-else>
<span>1b</span>
</div>
<button #click="toggleBlueBox">Toggle Blue Box</button>
</div>
<div id="container2">
<h2>Container 2</h2>
<h5>Type 5 or more characters for Green Box</h5>
<input
placeholder="Type 5 characters"
v-model="userInput"
#input="validateInputForGreenBox()"
/>
<div class="box3" v-if="displayGreen">
<span>2</span>
</div>
</div>
<div id="container3">
<p>
Why does <span class="bold">isBlueBoxDisplayed()</span> method trigger
when <span class="bold">validateInput()</span> is triggered?
</p>
<p>(see console for confirmation of this)</p>
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
displayBlue: false,
displayGreen: false,
userInput: "",
};
},
methods: {
toggleBlueBox() {
this.displayBlue = !this.displayBlue;
},
isBlueBoxDisplayed() {
console.log("isBlueBoxDisplayed() method activated!");
if (this.displayBlue) {
return true;
}
return false;
},
validateInputForGreenBox() {
console.log("validateInputForGreenBox() method Hit!");
if (this.userInput.length > 4) {
return (this.displayGreen = true);
}
this.displayGreen = false;
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
display: flex;
justify-content: space-between;
width: 100%;
}
#container1,
#container2 {
border-right: 2px solid grey;
}
div > span {
color: white;
}
.bold {
font-weight: 600;
}
.box1 {
width: 100px;
height: 100px;
background-color: blue;
}
.box2 {
width: 100px;
height: 100px;
background-color: red;
}
.box3 {
width: 100px;
height: 100px;
background-color: green;
}
</style>
Sandbox here:
https://codesandbox.io/s/gifted-matsumoto-lq2mj?file=/src/App.vue
The issue:
The two features have nothing to do with one another. And yet, when a user types into the input area (which triggers the validateInputForGreenBox() method, as it should) it triggers the isBlueBoxDisplayed() method (which should not be triggered).
On a large scale application that I have, this is causing some performance issues whereby multiple unrelated methods are being triggered. So why is this happening? And is there something that can be done so that unrelated methods don't trigger?
Although a simple answer, I've seen the struggle many times.
The issue here is that the functions that you pass to your events are being called immediately, almost as acting as an IIFE. Because of the existence of v-if on the page, you're causing a reflow which is triggering the methods again.
Short answer:
Don't use () when passing functions to events:
Good:
#input="validateInputForGreenBox"
Bad:
#input="validateInputForGreenBox()"
and the fiddle for proof

Blur event for custom vue component

What I have
A custom DropDown with a filter text input above. The DropDown can be opened independently from the filter text input.
What I want
The intended behavior would be, that the dropdown closes when the filter input loses focus and also when I click with the mouse outside of the DropDown, so that the DropDown loses the focus.
What I tried
Bind to the blur event on my root div element in the control, which doesn't fire at all.
I also couldn't find anything about internal component methods which I could override.
Code
<div #blur="onRootLostFocus">
...
</div>
...
...
...
onRootLostFocus() {
console.log('LostFocus');
this.deactivateSearchPanel();
this.deactivateSelectionPanel();
}
Solution
I missed, that a div needs tabindex="0" to be focusable, this fixed my problem
Something like this?
Answer: You need to set tabindex="0" to make it focusable.
Here an custom dropdown how you could do it:
Vue.component("dropdown", {
props: ["value"],
data(){
return {
open: false,
options: ["BMW", "Fiat", "Citroen", "Audi", "Tesla"]
}
},
methods: {
toggleDropdown() {
this.open = !this.open;
},
closeDropdown(){
this.open = false;
},
selectOption(option) {
this.$emit("input", option);
}
},
template: `<div class="dropdown">
<div #blur="closeDropdown" tabindex="0" ref="dropdown" #click="toggleDropdown" class="select">
{{ value }}
</div>
<div class="options" :style="{'max-height': open ? '300px' : '0px'}">
<div v-for="option in options" #mousedown="selectOption(option)" class="option">
{{ option }}
</div>
</div>
</div>`
})
new Vue({
el: "#app",
data: {
selectedCar: "BMW"
}
})
.dropdown {
width: 200px;
position: relative;
}
.select {
height: 40px;
position: absolute;
left: 0;
width: 100%;
background: green;
display: flex;
justify-content: center;
align-items: center;
color: white;
cursor: pointer;
}
.option {
width: 100%;
height: 40px;
background: darkgreen;
color: white;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.option:hover {
background: green;
}
.options {
overflow: hidden;
transition: max-height 200ms;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"> <p>
{{ selectedCar }}</p>
<dropdown v-model="selectedCar" />
</div>
Note there is also tabindex="-1" to make it not reachable via sequential keyboard navigation.
Also consider using a <button> instead because of accessibility concerns.
See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex

jquery form validation not working on checkbox

$(document).ready(function () {
$('#msg_opportunities_form').validate({
rules: {
text_message: {
required: true,
maxlength: 400
},
temrs_and_condp: {
required: true
}
},
messages: {
text_message: {
required: "Please enter Announcement Title",
maxlength: "Your Announcement Title must consist of at most 400 characters"
},
temrs_and_condp: "Please accept our terms"
},
errorElement: "em",
errorPlacement: function(error, element) {
// Add the `help-block` class to the error element
error.addClass("help-block");
if (element.prop("type") === "checkbox") {
error.insertAfter(element.parent("p"));
} else {
error.insertAfter(element);
}
},
highlight: function(element, errorClass, validClass) {
$(element).parents(".col-sm-5").addClass("has-error").removeClass("has-success");
},
unhighlight: function(element, errorClass, validClass) {
$(element).parents(".col-sm-5").addClass("has-success").removeClass("has-error");
}
});
$('#msg_opportunities_form').submit(function(event) {
console.log($(this).find(':input'));
if ($('#msg_opportunities_form').valid()) {
return true;
} else {
event.preventDefault();
}
});
});
.userSentInfo img {width: 97px;height: 97px;object-fit: cover;border-radius: 50%;}
.userSentDetials span {font-size: 20px;}
.sendMessage h3 {font-family:'louis_george_cafebold';}
textarea.sendMsgHere { border: 1px solid #acacac; height: 358px; resize: none; border-bottom: 0px;
margin-bottom: 0;}
.sumitBtnBox {position: relative;width: 100%;bottom:5px;background: #fff;padding: 0 18px;height: 60px;margin: 0 auto;left: 0;
right: 0;border-top: 1px solid #acacac;border-left: 1px solid #acacac;border-right:1px solid #acacac;
border-bottom: 1px solid #acacac; }
button.bg-blue.sendMsgBtn {border: none;width: 100px; padding: 6px; font-size: 18px; transition: all 0.3s;}
input#temrs_and_cond {display: none;}
.termsndcond + label { position: relative; font-size:16px; color: #605b5c; display: flex; align-items: center;}
.col-md-12.px-0.d-flex.userSentInfo.align-items-center { margin-top: 25px;}
button.bg-blue.sendMsgBtn:hover { background: transparent; color: #2d68b2; border: 1px solid #2d68b2;}
.col-md-8.sndMsgBox.col-12 { margin-top: 100px;}
.sndMsgBox div {color: #595959;font-size: 24px;letter-spacing: 0px;}
.sndMsgBox hr { margin: 34px auto; border-top: 1px solid #a8a8a8;}
.sndMsgBox h3 {font-family:'louis_george_cafebold'; font-size: 24px;}
.sndMsgBox div div { margin-bottom: 10px;}
.sndMsgBox div strong {font-family:'louis_george_cafebold';}
.ads-block { margin-bottom: 40px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/additional-methods.js"></script>
<form method="POST" action="{{url('/')}}/{{Request::path()}}" id="msg_opportunities_form" class="inline-form" enctype="multipart/form-data">
<h3 class="text-color-blue">Send Message </h3>
<textarea class="sendMsgHere" name="text_message" placeholder="Type Here"></textarea>
<p class="checkbox sumitBtnBox d-flex justify-content-between align-items-center">
<input name="temrs_and_condp" type="checkbox" value="1" id="temrs_and_cond" class="termsndcond">
<label for="temrs_and_cond"> I agree to Terms & Conditions </label>
</p>
<button class="bg-blue sendMsgBtn" type="submit"> Send</button>
</form>
the above code is for jquery from validation but it did't validate checkbox. i just need to check check box is required before submitting form . already done too many hard refresh , check on stack for checkbox everyone say just put required with true but that not working for me don't know why this is not working if i add any other field above or below checkbox they are working perfectly fine
already go through this link
thanks in advance
there are two problem's in my code first is console log just remove it for snippet . then it's work fine
second the major problem which i forgot to write is css file (question is updated now)
my designer put my check box to
display none
which cause the hole mess just remove and every then work magically in place of display none use this:
opacity: 0;position: absolute;
hope it will work for you guys too
To do this you have to use the :checked selector.
refer following code:
$('#form1').submit(function() {
if $('input:radio', this).is(':checked') {
} else {
alert('Please agree to terms and conditions!');
return false;
}
});

Measuring overflow is incorrect in Vue

I'm trying to make a overflow with tagging, which fades out in the beginning to give the user a hint that there's more. This is what it looks like:
I put the fading gradient as a :after inside the CSS and "activate" it by Vue's style binding, when scrollWidth > offsetWidth (overflow bigger than the box itself).
But the problem is that it sometimes (lags?) behind and does not calculate the scrollWidth right, especially when I enter a long word and then delete it. It doesn't "like" that and it says that the overflow is false, but there's no tag in the box. Basically this happens:
I tried to put the calculation inside this $nextTick(), but it didn't solve the issue. I also tried using Vue's keyDown, keyUp and keyPress listeners, but nothing solved this also.
This (also on CodePen) demonstrates the issue:
new Vue({
el: '#tagsinput',
data: {
input_value: "",
tags: []
},
methods: {
addTag: function() {
if (this.input_value > "") {
this.tags.push(this.input_value)
this.input_value = "";
// Refocus the text input, so it stays at the end
this.$refs.input.blur();
this.$nextTick(function() {
this.$refs.input.focus();
})
}
},
deleteTag: function() {
if (this.input_value == "") {
this.tags.pop()
}
}
}
})
.outter {
border: 1px solid red;
width: 250px;
overflow: hidden;
display: flex;
}
.inner {
border: 1px solid blue;
margin: 2px;
display: flex;
}
.tag {
border: 1px solid black;
margin: 2px;
}
input {
min-width: 80px;
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.2/vue.min.js"></script>
<div id="tagsinput">
<div class="outter" ref="outter">
<div class="inner" ref="inner">
<div class="tag" v-for="tag in tags">{{tag}}</div><input type="text" v-model="input_value" #keydown.enter="addTag" #keydown.delete="deleteTag">
</div>
</div>
Outter div scrollwidth: {{ $refs.outter ? $refs.outter.scrollWidth : null }}<br> Outter div offsetWidth: {{ $refs.outter ? $refs.outter.offsetWidth : null }}<br>
<br> Is overflowing: {{ ($refs.outter ? $refs.outter.scrollWidth : null) > ($refs.outter ?$refs.outter.offsetWidth : null) }}
</div>
<br><br> Type a really long word in, add and then delete it. "Is overflowing" will be the inverse, until you press Backspace <b>again</b>.
Any help is greatly appreciated.
You should call the check for overflow after the moment you've added or deleted the tag, so you check the overflow at the right moment. Vue isn't databinding an inline condition like that. The following code should work for you. It calls a checkOverflow function within $nextTick, setting a data-binded variable isOverflowed that you then can use to bind some styles.
new Vue({
el: '#tagsinput',
data: {
input_value: null,
tags: [],
isOverflowed: false
},
methods: {
addTag: function() {
if(this.input_value) {
this.tags.push(this.input_value)
this.input_value = null;
// Refocus the text input, so it stays at the end
this.$refs.input.blur();
this.$nextTick(function() {
this.$refs.input.focus();
this.checkOverflow()
})
}
},
deleteTag: function() {
if(!this.input_value) {
this.tags.pop()
this.$nextTick(function() {
this.checkOverflow()
})
}
},
checkOverflow: function() {
this.isOverflowed = (this.$refs.outter ? this.$refs.outter.scrollWidth : null) >
(this.$refs.outter ? this.$refs.outter.offsetWidth : null)
}
}
})
.outter {
border: 1px solid red;
width: 250px;
overflow: hidden;
display: flex;
}
.inner {
border: 1px solid blue;
margin: 2px;
display: flex;
}
.tag {
border: 1px solid black;
margin: 2px;
}
input {
min-width: 80px;
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="tagsinput">
<div class="outter" ref="outter">
<div class="inner" ref="inner">
<div class="tag" v-for="tag in tags">{{tag}}</div>
<input type="text" v-model="input_value" #keydown.enter="addTag" #keydown.delete="deleteTag" ref="input">
</div>
</div>
<br>
Is overflowing:
{{ isOverflowed }}
</div>
<br><br>
Type a really long word in, add and then delete it. "Is overflowing" will be the inverse, until you press Backspace <b>again</b>.
More of a CSS/HTML hack ...
Add <div id="spaceFade"></div> after <div id="tagsinput">, then add the following CSS :
#spaceFade {
background-image: linear-gradient(to right, rgba(255,255,255,1), rgba(255,255,255,1), rgba(0,0,0,0));
position : absolute;
height : 2em;
width : 3em;
}
#tagsinput {
position : relative;
}
.outter {
justify-content: flex-end;
}

select box change css class

Unfortunately I can not work it out with x-editable...
I´m trying to change a (hprimary) css class on select with x-editable. Here is my jsfiddel: jsfiddel (only with x-editable). Also, i tried It with a normal select button and it is working there. ( jsfiddel2 ) So what do I have to change in x-editable script to make it work?
html:
<div class="hpanel hprimary" id="overview">
</div>
<div><label class="control-label">TEST</label>
<a href="#" id="select" data-type="select" data-pk="1"data-value=""
data-title="" class="editable editable-click" style="color: gray;">not selected</a>
</div>
javascript:
$(function () {
$.fn.editable.defaults.mode = 'popup';
$('#select').editable({
prepend: "not selected",
placement: 'right',
source: [{
value: 1,
text: 'NTP(red)'
}, {
value: 2,
text: 'SUCCESS(green)'
}, {
value: 3,
text: 'OPTION(blue)'
}],
});
});
css:
.hpanel {
background-color: none;
border: none;
box-shadow: none;
margin-bottom: 25px
}
.hpanel.hprimary .panel-body {
border-top: 2px solid #34495e
}
.hpanel.hgreen .panel-body {
border-top: 2px solid #62cb31
}
.hpanel.hblue .panel-body {
border-top: 2px solid #3498db
}
.hpanel.hred .panel-body {
border-top: 2px solid #e74c3c
}
You can use the validate() callback option as described here to be alerted when the user has selected a value.
Based on your example, you would then use a regular expression to extract the color from the text value and add the appropriate class to the hpanel element.

Categories