Polymer handle click event from custom element child - javascript

I'm new to Polymer , I have a dom-repat custom element that contains a simple-overlay ,I want when clicking close button this overlay should close
this is the custom element
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-styles/typography.html">
<link rel="import" href="../overlay-layer/simple-overlay.html">
<dom-module is="feed-bdy">
<template items="{{items}}">
<style include="iron-flex iron-flex-alignment" >
:host{
--paper-button-ink-color: var(--paper-pink-a200);
--paper-button{
background-color: red !important;
color: red;
}
}
.custom{
color: red;
}
.content-bdy{
min-height: 120px;
}
.scrollable{
#apply(--layout-scroll);
max-width: 75%;
}
</style>
<div class="card-content">
<div class="ar-header">
<h3> [[items.fields.title]]</h3>
</div>
<div class="content-bdy"></div>
</div>
[[_renderHTML(items)]]
<div class="card-actions">
<paper-button class="custom" id="ar-[[items.fields.articleId]]" on-click="_openOverlay">إقراء المزيد !</paper-button>
<simple-overlay id="backdrop-[[items.fields.articleId]]" data-ar="backdrop-[[items.fields.articleId]]" with-backdrop class="layout scrollable">
[[_renderFullArticle(items)]]
<button id="dd">Close</button>
</simple-overlay>
<paper-button>
شارك
<iron-icon icon="reply"></iron-icon>
</paper-button>
</div>
</template>
<script>
Polymer({
is: 'feed-bdy',
listeners :{
'dd.click':'_closeOverlay'
},
_renderHTML: function(items) {
// firstp to get only the first pargarph to put in the home page
var ss= items.fields.body;
//console.log(this.$$(".card-content"));
var firstp = ss.substring(0,ss.search("</p>")+4);
this.$$(".content-bdy").innerHTML += firstp;
},
_renderFullArticle : function(items){
this.$$("simple-overlay").innerHTML +=items.fields.body;
},
_toggle : function(e){
var id = Polymer.dom(e).localTarget.title;
//console.log(id);
var moreInfo = document.getElementById(id);
// console.log(moreInfo);
var iconButton = Polymer.dom(e).localTarget;
iconButton.icon = moreInfo.opened ? 'hardware:keyboard-arrow-up'
: 'hardware:keyboard-arrow-down';
moreInfo.toggle();
},
_openOverlay : function(e){
//console.log('calling _openOverlay');
var id = Polymer.dom(e).localTarget.id.split('ar-')[1];
var dd = document.getElementById('backdrop-'+id);
dd.open();
},
_closeOverlay : function(e){
console.log(Polymer.dom(e));
console.log('calling _openOverlay');
var id = Polymer.dom(e).localTarget.id.split('ar-')[1];
// var dd = document.getElementById('backdrop-'+id);
/// dd.close();
}
});
</script>
</dom-module>
and in the index.html
<div class="video layout horizontal around-justified wrap" >
<template is="dom-repeat" items="[[ajaxResponse]]" >
<paper-card image="[[item.fields.image]]" class="flex-auto" wide-layout$="{{wide}}">
<feed-bdy items="[[item]]"></feed-bdy>
</paper-card>
</template>
</div>
so when clicking the close button the _closeOverlay should be fired and I tried to console messages as you can see , but no event was fired any advice

You only show part of your index.html file, but is the content you did show inside a <template is="dom-bind"> ?
Polymer doesn't work with databinding and events etc unless that stuff is.
These days (following Google I/O 2016) and the discussions about lazy loading etc I have stopped using the dom-bind approach and instead have a single custom element that then has all the functionality inside, including styling.

Related

How to open open a side panel upon a button press using vue.js?

I'm developing my first app with Vue and need some advice with trying to open a panel upon pressing a button in the header.
I'm starting with a basic HTML template, trying to add interactivity after pressing a button that's contained in the header.
When pressing the button, I'm getting the following message in the console:
vue.js:597 [Vue warn]: Invalid handler for event "click": got
undefined
(found in )
The code I'm using is as follows:
HTML:
<!-- Doctype HTML5 -->
<!DOCTYPE html>
<html lang="en" />
<head>
<link rel="stylesheet" href="css/normalize.css">
{{ $style := resources.Get "scss/main.scss" | toCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $style.Permalink }}">
<script src="js/vue.js"></script>
<script type="text/javascript" src="js/vue-proj-info.js"></script>
</head>
<body>
<header>
<div class="h-branding">
<div id="h-nLogo">
<img src="img/med-logo-rev.png"height="70" />
</div>
<div id="h-title">
<h1>Executive Blueprint</h1>
<p class="subheader"><span class="tr-tier">Tier 1</span> - <span class="tr-service">Executive</span></p>
</div>
</div>
<div id="h-toggles">
<div class="buttonGroup">
<button type="" name="tier1">Tier 1</button>
<button type="" name="tier2">Tier 2</button>
<button type="" name="tier3">Tier 3</button>
</div>
<div class="buttonGroup">
<button type="" name="executive">Executive</button>
<button type="" name="concierge">Concierge</button>
</div>
</div>
<proj-slideout ref="proj-slideout" id="proj-slideout" :class="{ isOpen: isOpen }">></proj-slideout>
<div id="h-infoButton">
<div class="buttonGroup">
<button type="button" name="projInfo" class="proj-slideout-opener"
#click="open">Project Information</button>
</div>
</div>
</header>
JS:
Vue.component('proj-slideout', {
template: '#proj-slideout',
props: ['show'],
data: () => ({
isOpen: false,
projContent: 'overview' /* overview, jtbd, tiers, files */
}),
methods: {
close() {
this.isOpen = false;
},
open() {
this.isOpen = true;
console.log('Open Panel');
}
}
});
document.addEventListener("DOMContentLoaded", function(event) {
var app = new Vue({
el: 'header'
})
});
SCSS:
#proj-slideout {
position: fixed;
top: 0;
right: 0;
width: 90vw;
height: 100vh;
padding: 30px;
display: flex;
flex-direction: row;
background-color: white;
transform: translateX(-100%);
transition: transform 0.6s ease(out-cubic);
display: none;
&.isOpen {
transform: translateX(0);
}
Any advice would be helpful!
In your code, #click="open" is refer to Vue parent component scope, so you should define isOpen and open in parent Vue component
document.addEventListener("DOMContentLoaded", function(event) {
var app = new Vue({
el: 'header',
data: () => ({
isOpen: false,
}),
methods: {
close() {
this.isOpen = false;
},
open() {
this.isOpen = true;
console.log('Open Panel');
}
}
})
});
All you need is to use v-show
On the template In your component tag add v-if or v-show like so :
<projContent v-show="isOpen" ... />
On the trigger button use directly the click event to set isOpen to false or true like this :
<button #click="isOpen = !isOpen" ... >Project Information</button>//or even better #click="isOpen ^= 1"
Now when you click the button it will set isOpen to its opposite value, if it's false it will become true and your projContent component will show up, if it's true, it will be set to false, hiding automatically your component, you don't even need to set a method to get the job done, it's directly set in the event.
Don't forget to remove display:none from your scss
If you need to add a transition animation here is the link "Vue transitions"

my script makes my whole bar to display none

I have a subscription box and im trying to make a X close button that remembers to not display next time with web storage or cookies. when i click the close button my whole side bar is set to display none. In stead of just id="gfxhsub" .
JavaScript
<script type="text/javascript">
window.onload = function(){
document.getElementById('mailclose').onclick = function(){
this.parentNode.parentNode.parentNode
.removeChild(this.parentNode.parentNode);
return false;
};
};
</script>
html
<div id="gfxhsub" style="margin: 2em 0.5em; height: auto;">
<span id='mailclose'><i class="fa fa-times"></i></span>
[newsletter_signup_form id=6]
</div>
You can achieve this by using the following code in your click event handler.
// 1st line: Select the div you want to hide.
// 2nd line: Set the style of the element to display: none;
var elem = document.querySelector('#gfxhsub');
elem.style.display = 'none';
Here's a working example.
#mailclose {
cursor: pointer;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script type="text/javascript">
window.onload = function() {
document.getElementById('mailclose').onclick = function() {
var elem = document.querySelector('#gfxhsub');
elem.style.display = 'none';
return false;
};
};
</script>
html
<div id="gfxhsub" style="margin: 2em 0.5em; height: auto;">
<span id='mailclose'><i class="fa fa-times"></i></span> [newsletter_signup_form id=6]
</div>

Clone working for an element but not for entire div

Explanation: I am trying to clone elements / div. I am trying to achieve it by right clicking on them opening up a context menu and clicking on "clone" option.
I have a very simple code, let me show you -
(function ($, window) {
$.fn.contextMenu = function (settings) {
return this.each(function () {
// Open context menu
$(this).on("contextmenu", function (e) {
// return native menu if pressing control
if (e.ctrlKey) return;
//open menu
var $menu = $(settings.menuSelector)
.data("invokedOn", $(e.target))
.show()
.css({
position: "absolute",
left: getMenuPosition(e.clientX, 'width', 'scrollLeft'),
top: getMenuPosition(e.clientY, 'height', 'scrollTop')
})
.off('click')
.on('click', 'a', function (e) {
$menu.hide();
var $invokedOn = $menu.data("invokedOn");
var $selectedMenu = $(e.target);
settings.menuSelected.call(this, $invokedOn, $selectedMenu);
});
return false;
});
//make sure menu closes on any click
$('body').click(function () {
$(settings.menuSelector).hide();
});
});
function getMenuPosition(mouse, direction, scrollDir) {
var win = $(window)[direction](),
scroll = $(window)[scrollDir](),
menu = $(settings.menuSelector)[direction](),
position = mouse + scroll;
// opening menu would pass the side of the page
if (mouse + menu > win && menu < mouse)
position -= menu;
return position;
}
};
})(jQuery, window);
$("#container").contextMenu({
menuSelector: "#contextMenu",
menuSelected: function (invokedOn, selectedMenu) {
var msg = "You selected the menu item '" + selectedMenu.text() +
"' on the value '" + invokedOn.text() + "'";
//var itsId = $(invokedOn).attr('id');
var selectedText = $(invokedOn).get(0).outerHTML;
var parentDiv = $(invokedOn).parent();
alert(selectedText);
if (selectedMenu.text() == "Clone"){
//alert("inside");
$(invokedOn).clone().insertAfter(invokedOn);
}
}
});
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css">
</head>
<body>
<div id="container">
<div id="content">content</div>
<div id="content2">
<p>This is p </p>
<h3> This is h3 </h3>
</div>
</div>
<ul id="contextMenu" class="dropdown-menu" role="menu" style="display:none" >
<li><a tabindex="-1" href="#">Clone</a></li>
<li><a tabindex="-1" href="#">Another action</a></li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="contextmenu.js"></script>
</body>
Run the code and Right click on "this is p" or "this is h3" and select clone, they will be cloned but i also want to clone entire div according to my selection. This requirement works for me on click but dont know how to do it by context menu, see this code here, the below code will work with left click, see this pic, i can clone entire div or single element depending on my area of click, same thing i want above with right click - https://www.dropbox.com/s/mqftyt96s75jc6b/Screenshot%202017-04-07%2013.38.30.png?dl=0
$('*').on('click', function(e){
e.stopPropagation()
var thisDiv_name = $(this).attr('id');
var thisDiv = $(this);
var parentDiv = $(this).parent();
// $(this).clone().appendTo(parentDiv);
$(this).attr('style','outline: #6c6b69 solid thin;');
$(this).clone().insertAfter(thisDiv);
//alert($(this).html());
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
</script>
</head>
<body>
<div id="main">
<div id="content">content</div>
<div id="content2">
<p>This is p </p>
<h3> This is h3 </h3>
</div>
<button id="button">show it</button>
</div>
</body>
</html>
To achieve this you could implement a new context menu item which clones the parent() element of one which triggered the event.
Also note that you can tidy up the logic by using a data attribute to specify the action to be performed instead of matching the text. Try this:
!function(a,b){a.fn.contextMenu=function(c){function d(d,e,f){var g=a(b)[e](),h=a(b)[f](),i=a(c.menuSelector)[e](),j=d+h;return d+i>g&&i<d&&(j-=i),j}return this.each(function(){a(this).on("contextmenu",function(b){if(!b.ctrlKey){var e=a(c.menuSelector).data("invokedOn",a(b.target)).show().css({position:"absolute",left:d(b.clientX,"width","scrollLeft"),top:d(b.clientY,"height","scrollTop")}).off("click").on("click","a",function(b){e.hide();var d=e.data("invokedOn"),f=a(b.target);c.menuSelected.call(this,d,f)});return!1}}),a("body").click(function(){a(c.menuSelector).hide()})})}}(jQuery,window);
$("#container").contextMenu({
menuSelector: "#contextMenu",
menuSelected: function($invokedOn, $selectedMenu) {
var action = $selectedMenu.data('action');
switch (action) {
case 'cloneEl':
$invokedOn.clone().insertAfter($invokedOn);
break;
case 'cloneParent':
var $parent = $invokedOn.parent();
$parent.clone().insertAfter($parent);
}
}
});
/* CSS is only to make the output more obvious */
p { background-color: #CC0; }
h3 { background-color: #0CC; }
#container > div {
border: 1px solid #C00;
margin: 5px;
}
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<div id="container">
<div id="content">content</div>
<div id="content2">
<p>This is p </p>
<h3>This is h3</h3>
</div>
</div>
<ul id="contextMenu" class="dropdown-menu" role="menu" style="display:none">
<li><a tabindex="-1" href="#" data-action="cloneEl">Clone</a></li>
<li><a tabindex="-1" href="#" data-action="cloneParent">Clone parent</a></li>
<li><a tabindex="-1" href="#" data-action="another">Another action</a></li>
</ul>

Polymer local dom

I played around with Polymer's local dom selector $$. I want to know if an element with a certain attribute exists. I wrote below example.
Is it by intention, that I cannot reach elements within other custom elements with the $$ selector?
How can I check for the existence of elements inside anothers element?
Is it good to go with document.querySelector?
<script src="https://elements.polymer-project.org/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.0.1/lib/polymer/polymer.html">
<dom-module id="my-moduleone">
<style>
:host {
height: 100%;
width: 100%;
display: block;
}
</style>
<template>
<div class="content-wrapper">
<content select="*" />
</div>
Counter 1: <span counter1>0</span>
<input type="button" value="Increment counter" on-click="_incrementCounter"/>
</template>
<script>
(function () {
Polymer({
is: 'my-moduleone',
_incrementCounter: function() {
this.$$('[counter1]').innerHTML++;
this.querySelector('[counter2]').innerHTML++;
this.$$('[counter3]').innerHTML++;
}
});
})();
</script>
</dom-module>
<dom-module id="my-moduletwo">
<style>
:host {
width: 100%;
display: inline-block;
}
.counter {
float: left;
height: 100px;
width: 100px;
display: block;
}
.blue {
background-color: lightblue;
}
.magenta {
background-color: magenta;
}
</style>
<template>
<content select="*" />
<span class="counter blue">
Counter 2: <span counter2>0</span>
</span>
<span class="counter magenta">
Counter 3: <span counter3>0</span>
</span>
</template>
<script>
(function () {
Polymer({
is: 'my-moduletwo'
});
})();
</script>
</dom-module>
<my-moduleone>
<my-moduletwo>
</my-moduletwo>
</my-moduleone>
You've said it yourself: this.$$ is a local dom selector. That means you cannot access elements that are added in the light dom. If you are going to access elements in the light dom (or access elements that aren't added in the local dom at registration time), use Polymer.dom instead. This is Polymer's suggested way of manipulating elements, be it in the light dom or the local dom. You also should not use document.querySelector in accessing elements that are inside the local dom of the element since this method cannot (by default) access the shadow dom.
Here is an example of using Polymer.dom:
<!doctype html>
<html>
<head>
<base href="http://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
</head>
<body>
<dom-module id="my-component-one">
<template>
<div class="content-wrapper">
<content select="*" />
</div>
Counter 1: <span counter1>0</span>
<input type="button" value="Increment counter" on-click="_incrementCounter" />
</template>
</dom-module>
<dom-module id="my-component-two">
<template>
<content select="*" />
<span class="counter blue">
Counter 2: <span counter2>0</span>
</span>
<span class="counter magenta">
Counter 3: <span counter3>0</span>
</span>
</template>
</dom-module>
<my-component-one>
<my-component-two></my-component-two>
</my-component-one>
<script>
(function() {
Polymer({
is: 'my-component-one',
_incrementCounter: function() {
// Note: Polymer.dom(this) accesses the light dom. Use Polymer.dom(this.root)
// to access the element's local dom
var componentTwo = Polymer.dom(this).querySelector('my-component-two');
if (!componentTwo) return; // don't do anything when there is no my-component-two
// access element's local dom by getting it's root property
var c2_counter2 = Polymer.dom(componentTwo.root).querySelector('[counter2]');
var c2_counter3 = Polymer.dom(componentTwo.root).querySelector('[counter3]');
var c1_counter1 = Polymer.dom(this.root).querySelector('[counter1]'); // this can be shortened to this.$$
var c1c1 = parseInt(c1_counter1.innerHTML);
var c2c2 = parseInt(c2_counter2.innerHTML);
var c2c3 = parseInt(c2_counter3.innerHTML);
c1_counter1.innerHTML = c1c1 + 1;
c2_counter2.innerHTML = c2c2 + 1;
c2_counter3.innerHTML = c2c3 + 1;
}
});
Polymer({
is: 'my-component-two'
});
})();
</script>
</body>
</html>

Div appears before javascript gets rendered

I'm using a script called Viral gate, it is utilized to unlock a content inside a div after someone clicks on Facebook Like Box, the only problem is that the div comes before the script, so when the page is loading it appears before the script gets rendered, during 5 seconds, or less, depending on the user connection, in other words, if the user wish he can pause the page when the div appears, so the javascript won't be rendered.
I tried inserting the script in head section, it didn't work, also tried inserting it before the div with adl-inside-gate class, same result.
This is my script along with the divs and content:
<div name="likebutton" style="padding-left: 370px; width:200px; padding-top:60px; position:relative;">
<!-- *** ADD THIS CODE AFTER YOUR PUBLIC CONTENT *** -->
<p class="adl-outside-gate">
<div class="adl-inside-gate" style="float:right">
<div class="linkado" style="width:130px; height:60px; background-color:#FF6600; border-width:4px; border-style:dashed; border-color:#FFFF00; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px;"> Clique aqui para visualizar o seu cupom.
</div>
</div>
<div style="float:left"> <b><!-- Sharing buttons --></b>
<!-- Botões -->
<!-- Botões -->
<div>
<div>
<div id="fb-root"> <b><script src="http://connect.facebook.net/pt_BR/all.js#xfbml=1&appId=1667889836683276"></script><fb:like font="" href="http://lucrebem.com.br" layout="box_count" send="false" show_faces="false" width="55"></fb:like></b>
</div>
</div>
</div>
<!-- Botões -->
<!-- Botões --> <b><!-- Here is the code --><script type="text/javascript">
ADL = {};
(function(namespace) {
function ViralGate() { };
ViralGate.prototype.setDisplay = function(className, value) {
var els = document.getElementsByClassName(className);
for (var i = 0; i < els.length; i++) {
els[i].style.display = value;
}
};
ViralGate.prototype.lock = function() {
this.setDisplay('adl-outside-gate', 'block');
this.setDisplay('adl-inside-gate', 'none');
};
ViralGate.prototype.unlock = function() {
this.setDisplay('adl-outside-gate', 'none');
this.setDisplay('adl-inside-gate', 'block');
}
ViralGate.prototype.afterLike = function(event) {
// event is the URL
ADL.viralGate.unlock();
};
namespace.viralGate = new ViralGate();
})(ADL);
ADL.viralGate.lock();
FB.Event.subscribe('edge.create', ADL.viralGate.afterLike);
// Google callback must be in global namespace
afterPlus = function(data) {
ADL.viralGate.afterPlus(data);
}
</script></b>
</div>
You'll need to default the display css property for your div that you want to default to hidden to "none". Something like:
<div style="display: none"></div>
This will hide it by default, allowing your js to show it later.

Categories