Popup dialogue error: Cannot read property 'show' of undefined - asp.net

I have a problem with showing popup dialogue using angularJS. I'm trying to exercise with the demo site.
https://material.angularjs.org/latest/demo/dialog.
following code is my controller js code.
(function () {
'use strict';
angular
.module('FramesPopup', ['ngRoute', 'ngMaterial' ])
.controller('PopupController', PopupController);
PopupController.$inject = ['$scope'];
function PopupController($scope, $mdDialog) {
$scope.title = 'PopupController';
$scope.status = ' ';
$scope.customFullscreen = false;
$scope.showAlert = function (ev) {
// Appending dialog to document.body to cover sidenav in docs app
// Modal dialogs should fully cover application
// to prevent interaction outside of dialog
$mdDialog.show(
$mdDialog.alert()
.parent(angular.element(document.querySelector('#popupContainer')))
.clickOutsideToClose(true)
.title('This is an alert title')
.textContent('You can specify some description text in here.')
.ariaLabel('Alert Dialog Demo')
.ok('Got it!')
.targetEvent(ev)
);
};
activate();
function activate() {
console.log("test");
}
}
})();

The $mdDialog service is missing from the $inject annotation list:
angular
.module('FramesPopup', ['ngRoute', 'ngMaterial' ])
.controller('PopupController', PopupController);
̶P̶o̶p̶u̶p̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶.̶$̶i̶n̶j̶e̶c̶t̶ ̶=̶ ̶[̶'̶$̶s̶c̶o̶p̶e̶'̶]̶;̶
PopupController.$inject = ['$scope','$mdDialog'];
function PopupController($scope, $mdDialog) {
$scope.title = 'PopupController';
$scope.status = ' ';
$scope.customFullscreen = false;
$scope.showAlert = function (ev) {
// Appending dialog to document.body to cover sidenav in docs app
// Modal dialogs should fully cover application
// to prevent interaction outside of dialog
$mdDialog.show(
$mdDialog.alert()

Related

Add element outside of an iframe

I have 2 vue projects. In one I am creating a simple component:
<template>
<button #click="importIframe">Click me</button>
</template>
<script>
export default {
name: 'App',
methods: {
importIframe() {
console.log(parent.document)
},
}
</script>
In the other project of vue, import with an iframe the project 01 with a script:
<script src="http://localhost:8081/myiframe.js"></script>
Project 01 is running in localhost:8081 and 02 in 8080. I have a my iframe script which is the one that creates the iframe and imports it into the body.
This is myiframe.js script:
ready(function () {
initIframe()
})
/**
* Auto execute javascript function
* #param callbackFunction
*/
function ready(callbackFunction) {
if (document.readyState != 'loading') callbackFunction()
else document.addEventListener('DOMContentLoaded', callbackFunction)
}
/**
* Initialize iframe
* #return {Promise<void>}
*/
function initIframe() {
// Set url
const baseUrl = 'http://localhost:8081'
// Create div tag
const divContainer = document.createElement('div')
divContainer.setAttribute('id', 'container-iframe')
// Create iframe tag
const iframe = document.createElement('iframe')
iframe.setAttribute('src', baseUrl)
divContainer.appendChild(iframe)
document.body.appendChild(divContainer)
}
What I want to achieve is that by clicking on the button. I should create a new div inside # container-iframe. If I select the iframe container it returns null. And if I select the parent of the iframe with parent.document. It gives me a security error, how can I add an element to the parent of the iframe?
This is a very common issue when you work with cross-domains.
Good news is that we have postMessage to send events between the iframe and the parent.
In the child (iframe button):
<script>
export default {
name: 'App',
methods: {
importIframe() {
parent.postMessage("clicked", "*");
},
}
</script>
Then listen in paranet:
function listenToChild() {
var eventMethod = window.addEventListener
? "addEventListener"
: "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod === "attachEvent"
? "onmessage"
: "message";
eventer(messageEvent, function (e) {
// if (e.origin !== 'http://the-trusted-iframe-origin.com') return;
if (e.data === "clicked" || e.message === "clicked")
alert('Message from iframe just came!');
// create a new div inside # container-iframe.
console.log(e);
});
}
Then add it to page load (ready function in your case)
More about the postMessage
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
https://gist.github.com/cirocosta/9f730967347faf9efb0b

Filereader progress in Vue.js component

I have a component that should to handle the upload file. It holds a bootstrap vue progress component.
I would to handle file loading of filereader.
This is part of vue.js component:
<b-form-file accept=".jpg, .png, .gif, jpeg" v-model="file" size="sm" #change="fileUpload"></b-form-file>
<b-progress :value="progress" :max="maxvalue" show-progress animated></b-progress>
This is my data:
data () {
return {
...
file:null,
progress:0,
maxvalue:100
}
},
This is my code:
fileUpload(ev){
var files = ev.target.files || ev.dataTransfer.files;
const file=files[0];
var reader = new FileReader();
let _vue=this;
reader.onprogress=function(e){
let progress=Math.round((e.loaded / e.total) * 100);
if(progress<100){_vue.progress=progress;}
};
reader.onload = function(event) {
var dataURL = event.target.result;
let image=new Image();
if(file.size>3000000) {
_vue.form.file=null;
alert('Dimensioni file eccessive');
return;
}
image.onload=function(){
_vue.$refs.card.style.maxWidth='250px';
_vue.$refs.card.style.width=`${this.width}px`;
}
image.src=dataURL;
_vue.form.file=dataURL;
};
reader.readAsDataURL(file);
}
If I set an alert, I get the progress values else no.
I noted if I setting two alert sequentially, I see the first alert for every value until the end and then the other one in reverse.
Sorry for my english
I resolved.
The link that resolved my issue:
link
Thanks

Fullcalendar using resources as a function with select menu

Using Fullcalendar 4, I am trying to show/hide my resources using a select menu. When the user selects one of the providers from a menu, I want to only show that one resourc's events.
Above my fullcalendar I have my select menu:
<select id="toggle_providers_calendar" class="form-control" >
<option value="1" selected>Screech Powers</option>
<option value="2">Slater</option>
</select>
I am gathering the resources I need using an ajax call on my included fullcalendar.php page. I am storing them in an object and then trying to control which resources are shown onscreen:
document.addEventListener('DOMContentLoaded', function() {
var resourceData = [];
$.getJSON('ajax_get_json.php?what=schedule_providers_at_location',
function(data) {
$.each(data, function(index) {
resourceData.push({
id: data[index].value,
title: data[index].text
});
});
console.log(resourceData);
});
//below, set the visible resources to whatever is selected in the menu
//using 1 in order for that to show at start
var visibleResourceIds = ["1"];
//below, get the selected id when the the menu is changed and use that in the toggle resource function
$('#toggle_providers_calendar').change(function() {
toggleResource($('#toggle_providers_calendar').val());
});
var calendar_full = document.getElementById('calendar_full');
var calendar = new FullCalendar.Calendar(calendar_full, {
events: {
url: 'ajax_get_json.php?what=location_appointments'
},
height: 700,
resources: function(fetchInfo, successCallback, failureCallback) {
// below, I am trying to filter resources by whether their id is in visibleResourceIds.
var filteredResources = [];
filteredResources = resourceData.filter(function(x) {
return visibleResourceIds.indexOf(x.id) !== -1;
});
successCallback(filteredResources);
},
...
});
// below, my toggle_providers_calendar will trigger this function. Feed it resourceId.
function toggleResource(resourceId) {
var index = visibleResourceIds.indexOf(resourceId);
if (index !== -1) {
visibleResourceIds.splice(index, 1);
} else {
visibleResourceIds.push(resourceId);
}
calendar.refetchResources();
}
To make sure the getJSON is working, I have console.log(resourceData). The information in the console once it's gathered is:
[{id: '1', title: 'Screech Powers'}, {id: '2', title: 'Slater}]
... the above are the correct resources that can be chosen/rendered. So that seems to be okay.
On page load, no resources show at all, when resource id of '1' (Screech Powers) should be shown per my code. Well, at least, that's what I am trying to do right now.
When the menu changes, resources will show/hide, but not based on what's selected; the logic of only showing what is selected in the menu doesn't seem to be working.
I used to use a URL request for my resources: 'ajax_get_json.php?what=schedule_providers_at_location', and it worked fine! All resources show then their events properly. I am just trying to modify it by using a menu to show/hide the resources as needed.
Here's what I'm doing to make it happen so far! In case someone comes across this post ever, this will help.
Here's my code before my fullcalendar code.
var resourceData = [];
var visibleResourceIds = [];
$.getJSON('ajax_get_json.php?what=schedule_providers_at_location',
function(data) {
$.each(data, function(index) {
resourceData.push({
id: data[index].value,
title: data[index].text
});
});
});
$('#toggle_providers_calendar').change(function() {
toggleResource($('#toggle_providers_calendar').val());
});
My select menu with id 'toggle_providers_calendar' is the same as my original post. My fullcalendar resources as a function is the same too.
After the calendar is rendered, here are the changes I made to my toggle resources function:
// menu button/dropdown will trigger this function. Feed it resourceId.
function toggleResource(resourceId) {
visibleResourceIds = [];
//if select all... see if undefined from loading on initial load = true
if ((resourceId == '') || (resourceId === undefined)) {
$.map( resourceData, function( value, index ) {
visibleResourceIds.push(value.id);
});
}
var index = visibleResourceIds.indexOf(resourceId);
if (index !== -1) {
visibleResourceIds.splice(index, 1);
} else {
visibleResourceIds.push(resourceId);
}
calendar.refetchResources();
}
This causes the resources to show and hide properly. If the user selects "Show All" that works too!
In order to have a default resource show on load, I add this to my fullcalendar script:
loading: function(bool) {
if (bool) {
//insert code if still loading
$('.loader').show();
} else {
$('.loader').hide();
if (initial_load) {
initial_load = false;
//code here once done loading and initial_load = true
var default_resource_to_show = "<?php echo $default_provider; ?>";
if (default_resource_to_show) {
//set the menu to that provider and trigger the change event to toggleresrource()
$('#toggle_providers_calendar').val(default_provider).change();
} else {
//pass in nothing meaning 'select all' providers for scheduler to see
toggleResource();
}
}
}
},
I am using a bool variable of initial_load to see if the page was just loaded (basically not loading data without a page refresh). The bool of initial_load = true is set outside of DOMContentLoaded
<script>
//show selected date in title box
var initial_load = true;
document.addEventListener('DOMContentLoaded', function() {
My only current problem is that when toggleResource function is called, the all day vertical time block boundaries don't line up with the rest of the scheduler. Once I start navigating, they do, but I don't understand why it looks like this on initial load or when toggleResource() is called:
Any thoughts on how to correct the alignment of the allday vertical blocks?

Removing a window event listener in Template.onDestroyed

I have two templates that each contain a Vimeo iframe player. I'm using FlowRouter to render the templates through {{> Template.dynamic template=main}} on the main layout.
In both templates I add listeners for video events in onCreated
Template.view.onCreated( function() {
var self = this;
if (window.addEventListener) {
window.addEventListener('message', function(event) {
viewMessageReceived(event, self)}, false);
} else {
window.attachEvent('onmessage', function(event){
viewMessageReceived(event, self)}, false);
}
});
and destroy them in onDestroyed
Template.view.onDestroyed( function() {
if (window.removeEventListener) {
console.log('view remove');
window.removeEventListener('message', function(event) {
viewMessageReceived(event, self)}, false);
} else {
window.detachEvent('onmessage', function(event){
viewMessageReceived(event, self)}, false);
}
});
And here is the function being called by the anonymous event handler:
function viewMessageReceived(event, self) {
// Handle messages from the vimeo player only
if (!(/^https?:\/\/player.vimeo.com/).test(event.origin)) {
return false;
}
if (self.playerOrigin === '*') {
self.playerOrigin = event.origin;
}
var data = JSON.parse(event.data);
switch (data.event) {
case "ready":
initializePlayer(self);
break;
case "playProgress":
self.playerTime.set(data.data.seconds);
if (self.duration === '*') self.duration = data.data.duration;
break;
case "play":
self.playerStatus.set("playing");
break;
case "pause":
self.playerStatus.set("paused");
break;
}
}
When I switch to a different template, onDestroyed runs and my console.log('view remove') fires, as expected.
But then when I navigate to the page that loads the other template with a video player, a Vimeo "playProgress" message arrives that is received by the event handler in the previous video template, which was supposed to have been removed a while ago. This throws an error because the previous template has been destroyed.
Uncaught TypeError: Cannot read property 'contentWindow' of undefined
which comes from the last line in this function:
function post(template, action, value) {
console.log('view action: %s value: %s', action, value);
var data = {method: action};
if (value) data.value = value;
var message = JSON.stringify(data);
template.player[0].contentWindow.postMessage(message, template.playerOrigin);
}
Each of the video-containing templates have their own .js file, so they each have a their own post function declaration. My understanding is that defining a function that way scopes the function just to the page.
It's only one message that arrives for the wrong player. After that, they arrive for the currently loaded player.
Why does the Vimeo message event arrive or get handled after I've already destroyed the template and when I've moved to another player?
A quote from the W3Schools website regarding the removeEventListener() method:
// Attach an event handler to <div>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);
// Remove the event handler from <div>
document.getElementById("myDIV").removeEventListener("mousemove", myFunction);
Note: To remove event handlers, the function specified with the
addEventListener() method must be an external function, like in the
example above (myFunction).
Anonymous functions, like "element.removeEventListener("event",
function(){ myScript });" will not work.
For this to work, you'll need to move your function definition somewhere outside of the onRendered and onDestroyed events, and just pass the function name in the add/remove event listeners.

Media editor backbone js: Get the current action

I'm creating a plugin that adds an option to the native WP gallery.
When a new gallery is created (clicking the "Create Gallery" button in the media popup), a 'select' element is added, and I have a backbone event listening for the 'change' event of this 'select'.
However, I only want to listen for the change event when the gallery is being newly created, rather than when editing an existing gallery.
My code so far is:
wp.media.view.Settings.Gallery = wp.media.view.Settings.Gallery.extend({
events: function() {
var the_events = {};
//NEED TO GET STATE (ie, 'creating gallery for first time' rather than 'edit gallery'....
var is_create_gallery = true;
//IF WE'RE EDITING, SET IT TO FALSE
//--here--
if (is_create_gallery) {
_.extend( the_events, { 'change select[data-setting="gallerytype"]' : 'gallerytypechanged' } );
}
return the_events;
},
gallerytypechanged: function( e ){
e.preventDefault();
var self = this;
var gallery_type = jQuery( e.currentTarget ).val();
if( gallery_type != 'native' ){
self.update.apply( self, ['gallerytype'] );
}
return self;
},
template: function(view) {
return wp.media.template('gallery-settings')(view) + wp.media.template('gallery-type')(view);
},
});
Basically the --here-- code should be a check to determine whether we're editing an existing gallery, or creating a new one.
Does anybody know where to check which state we're in?
Thanks!
I assume you can detect the state of the gallery outside of your Backbone View.
You could set the is_create_gallery state when initializing the backbone view, then call your view constructor with the custom argument:
var newGallery = // determine the gallery state
var view = new wp.media.view.Settings.Gallery({newGallery: newGallery});
You can access the passed argument in your initialize function like this:
initialize: function (options) {
if (options.newGallery) {
_.extend(this.events, {
'change select[data-setting="gallerytype"]' : 'gallerytypechanged'
});
}
}
Since your events map will be either empty or contain one event, I would remove the events key completely and do the events initialization from initialize.

Resources