How to use Modal Pop up with Material Design Lite? - modal-dialog

I recently started using the latest Desktop version of Google Material Design Lite, I figured it doesn't have a modal pop up and the team has not yet implemented it for the next release.
I have tried to include bootstrap model into it, but thats not working infect seems pretty messed, I believe with the classes/styles clashing with each others.
Any Idea what will work good as an replacement ??
Thanks for your help.

I was also looking for a similar plugin and then I found mdl-jquery-modal-dialog
https://github.com/oRRs/mdl-jquery-modal-dialog
I used this because the other one I found was having issue on IE11. This one works fine.
<button id="show-info" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
Show Info
</button>
Here a JSFiddle: https://jsfiddle.net/w5cpw7yf/

I came up with a pure JavaScript Solution for this
You can use the default bootstrap data attributes for the buttons, and make sure that your buttons and modals have their own unique IDs.
You need to have Material Design Lite's JS included before using this JavaScript
Check out the code. Any reviews are welcomed. :)
// Selecting all Buttons with data-toggle="modal", i.e. the modal triggers on the page
var modalTriggers = document.querySelectorAll('[data-toggle="modal"]');
// Getting the target modal of every button and applying listeners
for (var i = modalTriggers.length - 1; i >= 0; i--) {
var t = modalTriggers[i].getAttribute('data-target');
var id = '#' + modalTriggers[i].getAttribute('id');
modalProcess(t, id);
}
/**
* It applies the listeners to modal and modal triggers
* #param {string} selector [The Dialog ID]
* #param {string} button [The Dialog triggering Button ID]
*/
function modalProcess(selector, button) {
var dialog = document.querySelector(selector);
var showDialogButton = document.querySelector(button);
if (dialog) {
if (!dialog.showModal) {
dialogPolyfill.registerDialog(dialog);
}
showDialogButton.addEventListener('click', function() {
dialog.showModal();
});
dialog.querySelector('.close').addEventListener('click', function() {
dialog.close();
});
}
}
<!-- Button to trigger Modal-->
<button class="mdl-button mdl-js-button" id="show-dialog" data-toggle="modal" data-target="#upload-pic">
Show Modal
</button>
<!-- Modal -->
<dialog id="upload-pic" class="mdl-dialog mdl-typography--text-center">
<span class="close">×</span>
<h4 class="mdl-dialog__title">Hello World</h4>
<div class="mdl-dialog__content">
<p>This is some content</p>
</div>
</dialog>

I use MDL with bootstrap and the modal is displayed correctly after adding the data-backdrop attribute this to the modal element:
<dialog data-backdrop="false">
Hope it helps!

Related

Jquery not working when click ajax button

I use jquery datepicker and it not display after I click ajax button.
Is there any way to show datepicker again after click? I use wicket 8.
BasePage.java
public class BasePage extends WebPage {
...
}
BasePage.html
<body>
...
<script src="/js/jquery.min.js"></script>
<script src="/js/jqueryui.min.js"></script>
<script src="/js/main.js"></script>
</body>
HomePage.java
public class HomePage extends BasePage {
public HomePage() {
SearchForm searchForm = new SearchForm();
Form<SearchForm> form = new Form<>(new CompoundPropertyModel<SearchForm>(searchForm))
AjaxButton btn = new AjaxButton() {
protected void onSubmit(AjaxRequest target) {
// Handle search data
...
target.add(form);
}
};
TextField<String> date = new TextField<>("searchDate");
form.add(date);
form.add(btn);
}
}
HomePage.html
<wicket:extend>
<form wicket:id="form">
<input wicket:id="searchDate" class="datepicker" />
<button wicket:id="btn">Search</button>
</form>
</wicket:extend>
main.js
$(function() {
$(".datepicker").datepicker();
...
});
After click ajax button all script in file main.js not working
Please help me.
when you update form via AJAX you replace each element inside it, which includes the input field you use with datepicker. But doing so you loose the javascript setting done by main.js when page was first loaded.
You can solve this in two ways. First, you could update only those elements that need to be refreshed, for example the component that you use to show search result (I suppose there must be such an element in your code).
The second solution, more heavier and complicated, is to make a custom TextField component that execute the datepicker javascript code each time is rendered.
An example of such solution can be found is in the user guide: https://wicket-guide.herokuapp.com/wicket/bookmarkable/org.wicketTutorial.ajaxdatepicker.HomePage
I would recommend to follow the first solution as it's more natural and simpler and requires less code.
UPDATE:
If you want to refresh the textfield another simple solution is to use target.appendJavaScript​ to reapply the datepicker plugin:
target.add("$('#" + date.getMarkupId() + "').datepicker();");
this should add the datepicker to the fresh new field.

Ionic 2 Updating Button Text and Event on Click

Sorry if this sounds very obvious but I am new to Ionic 2 / Angular 2. Upon submitting a form, I need to update the button text and click event, ie:
first click on button = submit form + update button text to "Next"
second click on button = trigger goToNext()
I managed to update the button text but not update the click event (to goToNext() ).
.html
<form (ngSubmit)="logForm(i)">
<ion-item>
<ion-input type="text" [(ngModel)]="form.userinput[i]" name="userinput[i]"></ion-input>
</ion-item>
<button ion-button block type="submit" (click)="setNext($event.target, 'Next')">Check</button>
</form>
.ts
setNext(element, text){
element.textContent = 'Next';
}
goToNext(){
// go to Next Page
}
Ideally you change your design a bit to keep a variable that stores state of your 'Controller'. e.g. stores PageNumber. and then behave differently based on what page you are on. So I suggest change design a bit.
But to answer your current question without major change, you can bind the handler dynamically the same way you bind the text. then in the first handler, change the handler for the next click. the default values for handler and text will decide which one is going the be used initially
handler = this.setNext;
text = 'first text';
setNext(){
alert('handler1 called');
this.handler = this.goToNext;
this.text = 'other text';
}
goToNext(){
alert('second called');
// go to Next Page
}
and in your html you go like
<button ion-button block type="submit" (click)="handler()">{{text}}</button>
You can use n00b answer or something like this:
in html file:
<button ion-button block type="submit" (click)="check()">{{btn_txt}}</button>
in ts file:
btn_txt = 'Check';
check() {
if (this.btn_txt == 'Check') {
//do some logic
this.btn_txt = 'Next';
} else {
console.log('go to next page');
}
}

slideChangeStart event does not fire when I swipe

In my Ionic 1.3.1 app I am using the ion-slides component to display sections of a questionnaire:
<ion-slides options="vm.options" slider="data.slider">
<ion-slide-page ng-repeat="s in ::vm.sections">
<div class="bar bar-header bar-positive">
<button class="button button-small button-icon icon ion-chevron-left"
ng-click="vm.previous()"
ng-show="::$index !== 0"></button>
<h1 class="title">{{::s.text}}</h1>
<button class="button button-small button-icon icon ion-chevron-right"
ng-click="vm.next()"
ng-show="::($index + 1) < vm.sections.length"></button>
</div>
<ion-content class="has-header">
<div ng-if="s.include" ng-show="s.show">
<!--My content-->
</div>
</ion-content>
</ion-slide-page>
</ion-slides>
In my controller I listen for the slideChangeStart:
$scope.$on("$ionicSlides.slideChangeStart", function (event, data) {
alert('slideChangeStart');
vm.activeIndex = slider.activeIndex;
vm.propertySurvey.CurrentSectionIndex = vm.activeIndex;
//include is used on an ng-if so elements are removed from the dom
//and the number of watchers is reduced
//also, the slider displays the contents of the
//previous slide unless they are explicitly hidden
vm.sections[slider.previousIndex].include = false;
vm.sections[slider.previousIndex].show = false;
initialiseQuestions(vm.activeIndex);
});
When I click on my previous and next buttons, which call slider.slidePrev() or slider.slideNext(), the slideChangeStart event fires - and I see the alert. But if I slide the page using a gesture - the header changes as I expect but the event does not fire. I've tried switching the swipe off in my options without success (not my preferred solution anyway):
vm.options = {
noSwiping: true,
effect: 'fade'
}
UPDATE
I tried using slideChangeEnd but that event isn't firing either.
So I moved all my code into a single gotoSlide(index) method that I call from my next, previous and pagerClick methods - so that I don't rely on the ion-slides event.
And I added Ionic on-swipe directives to my ion-slide-page component to see if they would work:
<ion-slide-page ng-repeat="s in ::vm.sections"
on-swipe-left="vm.next()"
on-swipe-right="vm.previous()">
That made the swipe work in the Ripple emulator (where it wasn't working at all before), but it still doesn't work on any of my android devices. Again, the swipe events don't seem to fire.
I am using the Crosswalk plugin
The problem goes away if I remove the effect option. So this works:
vm.options = {
noSwiping: false,
speed: 300
}
And, since these are the default values anyway, I ended up removing the options object altogether.
NB replacing 'fade' with 'slide' did not work
Reference:
http://ionicframework.com/docs/api/directive/ionSlides/
I had a similar problem, and the above answer did not work for me, so I thought I'd share what did:
Per the Swiper API (which underlies ion-slides), you can add event based call backs directly to the widget.
The following worked for me (assuming the scope.slider object...)
//the 'slideChangeStart' event has a slider argument in its callback
scope.slider.on('slideChangeStart', function(slider) {
//do stuff - maybe you want to store the activeIndex
scope.indexIReallyCareAbout = slider.activeIndex;
});
The Swiper API gives a list of events that can named in the 'on' callback function under the header Callbacks

AngularJS and Tab Order (Disabled Buttons)

I have a form, and I'm navigating only with TAB. Tab order should be input > select > button, but because of the ng-disable on the SUBMIT, on certain browsers the TAB out of the select will kick you somewhere else.
HTML
<div ng-app="myApp">
<div ng-controller="FirstCtrl">
<form name="myForm" ng-submit="submit()" novalidate>
First Name: <input type="text" ng-model="Data.FirstName" required><br>
Last Name: <select ng-model="Data.LastName" required>
<option value="Bigglesworth">Bigglesworth</option>
<option value="Burgermeister">Burgermeister</option>
</select><br>
<input type="submit" value="Submit" ng-disabled="myForm.$invalid" />
</form>
</div>
</div>
JS
var myApp = angular.module('myApp', []);
myApp.factory('Data', function(){
return {
FirstName: '',
LastName: ''
};
});
myApp.controller('FirstCtrl', function( $scope, Data ){
$scope.Data = Data;
$scope.submit = function() {
console.log('you just submitted, foolio');
}
});
JsFiddle here.
On Mac FF the final tab kicks you to the address bar before enabling the submit button. Mac Chrome works as you'd expect, focusing on the submit button after final tab. I know Windows is janky, but don't have exact specs to post.
Thoughts? How can I do this in a fool-proof fashion?
EDIT
I've selected #David B.'s answer as it's the best Angular solution. I ended up using a somewhat hidden element right after the the submit button so the focus would stay in the same general area. Lame and hacky, I know, but for a tight deadline it worked.
<h3><button class="fakebtn_hack">Confirmation</button></h3>
<style>.fakebtn_hack {background:none; border:none; color: #FF6319; cursor: default; font-size: 1em; padding: 0;}</style>
This happens because Firefox doesn't send a change event on key-driven changes of the select. Angular doesn't see the change until the tab is hit, so the submit button isn't enabled until after the tab has been processed by the browser (and focus sent to some other element, e.g., the address bar). The W3C standard suggests not sending the event until the control loses focus, although Chrome sends one for any change and Firefox does if the change was mouse-driven.
See the angularjs issue tracker for more: https://github.com/angular/angular.js/issues/4216
As suggested in the issue tracker, solve it by manually issuing the change event via the following select directive (http://jsfiddle.net/j5ZzE/):
myApp.directive("select", function () {
return {
restrict: "E",
require: "?ngModel",
scope: false,
link: function (scope, element, attrs, ngModel) {
if (!ngModel) {
return;
}
element.bind("keyup", function () {
element.trigger("change");
})
}
}
})
You'll need JQuery loaded before AngularJS to have the trigger function available on the element object.
Manually include an empty option (<option value=""></option>) in your select or the first option will be auto-selected when the control receives focus.
Unlike the default behavior, this empty option will not disappear after selecting a real option. I suppose you could remove the empty option by declaring all the options via ng-options or ng-repeat and then removing the empty one from the bound scope once a real option has been selected, but I've never tried it.

Programmatical changes will not reflect in knockout viewmodel

To change the status of a checkbox with javascript doesn't correspond to the spirit of MVVM. But I'm creating a general javascript library for better looking standard controls like checkbox, radio button or selectbox.
Based on the following viewmodel:
function MyViewModel() {
var self = this;
self.ok = ko.observable();
};
var vm = new MyViewModel();
ko.applyBindings(vm);
But I get a problem in conjunction with knockout when I change the checked status of a checkbox programmatically:
document.getElementById('chk').checked = true
The change will not appear in the property of the viewmodel. But when I click the checkbox all works fine.
Look at http://jsfiddle.net/KWdZB/1/
Is there any workaround?
Your problem is that ko subscribes on the click event inside the checked binding:
ko.utils.registerEventHandler(element, "click", updateHandler);
But changing the checked attribute won't trigger the click event so ko won't be notified.
If you manually trigger the click event after the attribute change it can work...
I don't know how to do it with pure javascript but with jQuery you can write:
$('#chk').attr('checked', true).triggerHandler('click')
You can test it in this JSFiddle.
This is normal because the checked binding handlers doesn't subscribe to the checked change event but subscribe to the click event handler (You can see on source file at the checked binding handlers code).
If you need to change value with click, you must to do with the ok observable value.
There is the HTML
<div>
<input type="checkbox" id="chk" data-bind="checked: ok"/><br>
<input type="button" id="btnCheck" value="Check" data-bind="click: Check"/>
<input type="button" id="btnUnCheck" value="Uncheck" data-bind="click:Uncheck"/>
</div>
<div>
Value: <span data-bind="text: ok"></span>
</div>
And the javascript :
function MyViewModel() {
var self = this;
self.ok = ko.observable();
self.Check = function(){
self.ok(true);
}
self.Uncheck = function(){
self.ok(false);
}
};
vm = new MyViewModel();
ko.applyBindings(vm);
​
​
You can see it in this fiddle.