I am using swiper.js and fancybox v3 to create a popup gallery. One of the slide contain a video, however after I have click and open popup, the video will load and start playing whatever which slide I landed. I have tried to use any events to stop pause the video but it still can't work. Anyone got a solutions?
Here is a codepen example:
$(document).ready(function () {
var mySwiper = new Swiper('.swiper-container', {
init: false,
pagination: {
el: '.swiper-pagination',
observer: true,
observeParents: true,
on: {
slideChangeTransitionStart: function () {
$('.swiper-slide').find('video').each(function () {
console.log(this);
this.pause();
});
},
slideChangeTransitionEnd: function () {
$('.swiper-slide').find('video').each(function () {
this.pause();
});
}
}
},
})
$('.fancybox-trigger').click(function (e) {
e.preventDefault();
var thisTarget = $(this).data('index');
$.fancybox.open({
src: "#lightbox",
type: 'inline',
opts: {
toolbar: false,
defaultType: 'inline',
autoFocus: true,
touch: false,
afterLoad: function () {
mySwiper.init();
mySwiper.slideTo(thisTarget - 1)
$('swiper-slide').find('video').each(function () {
this.pause();
})
}
}
})
})
});
https://codepen.io/anon/pen/mKOwag?editors=0010
I am not swiper expert, therefore I can not explain why, but I found that callbacks work if you add them like this:
mySwiper.on('slideChange', function() {
$('.swiper-slide').find('video').each(function() {
this.pause();
});
});
Demo - https://codepen.io/anon/pen/ERNogR
I am new in vuejs2 development. I am working in a modal development. I kept the modal body code in a component and displaying that modal in another component. I have below code in modal body component.
<script>
import SemanticModal from 'vue-ya-semantic-modal'
export default {
components: { SemanticModal: SemanticModal() },
name: 'ModalBody',
props: ['active1',],
data() {
return {
visible: false
}
},
methods: {
close() {
this.$emit('sendValue', false); //this is working
this.visible = false
},
open () {
this.visible = true
},
},
watch: {
active1 () {
if (this.active1 && !this.visible) this.open()
else if (!this.active1 && this.visible) this.close()
},
},
directives: {
'click-outside': {
bind: function(el, binding, vNode) {
el.onclick = function(e) {
var modal = document.getElementsByClassName("modal");
el.addEventListener('click', function (event) {
if (!modal[0].contains(event.target)) {
vNode.context.$emit('sendValue', false); //this is not working
this.visible = false
}
})
}
}
}
}
}
I am calling that model (child) component in parent component like below
<modal-body :active1="active1" #sendValue="active1 = $event"></modal-body>
I need to change the below props active1 value to false from child to parent component.
You are handling click event by using directives.
According to your requirement , clickoutside directive should emit sendValue event from child to parent. But i feel like your code has some complications.
The proper code to accomplish your scenario is below
directives: {
'clickoutside': {
bind: function(el, binding, vNode) {
el.onclick = function(e) {
console.log("binding clicked");
vNode.context.$emit('sendValue', false);
}
}
}
}
if your objective is to use click event you can use #click binding to accomplish the same
I saw in the UI5 "Explored" examples a press event with what looks to be an array:
press="[handleViewSettingsDialogFilterBarPressed, views.control.tableViewSettingsDialog]"
Example on line 25
I understand how normal press events work. What does using an array like this do? I couldn't find documentation on it, so any info on how it works or a link to where it's documented would be very helpful.
It is a just a shortcut. Maybe it is easier to see this in an example here. Both handlers call the same function in the Controller.
sap.ui.jsview("myView.Template", {
getControllerName: function() {
return "myView.Template";
},
createContent: function(oController) {
var oBox = new sap.m.HBox({
items: [
new sap.m.Button({
text: 'First',
press: function(oEvent) {
oController.press(oEvent);
}
}),
new sap.m.Button({
text: 'Second',
press: [oController.press, oController]
})
]
});
return oBox;
}
});
sap.ui.define([
'jquery.sap.global',
'sap/ui/core/mvc/Controller',
], function(jQuery, Controller) {
"use strict";
var TableController = Controller.extend("myView.Template", {
press: function(oEvent) {
alert('press');
}
});
return TableController;
});
//Instantiate View
var view = sap.ui.view({
type: sap.ui.core.mvc.ViewType.JS,
viewName: "myView.Template"
});
view.placeAt("content");
the first item in the array is function to call and the second item is the binding object.
Thanks
Check out the description of the press Event property under the sap.m.Toolbar Constructor:
Events press : fnListenerFunction or [fnListenerFunction,
oListenerObject] or [oData, fnListenerFunction, oListenerObject]
I am wondering if you can pass a controller to the $ionicModal service. Something like.
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope,
controller: 'MyModalCotroller'
})
A little context: I would like to have a modal that is distributed across the app and I dont want to repeat all the methods (hide, show, buttons inside the modal) in every controller and I would like to remove the methods from the 'Main Controller' to keep things clean. This would encapsulate the functionality of the modal.
Is there a way to do this.?
Thanks
Just add the controller you want to use in the body of the html of the modal. I created a fiddle to show you an example based off the one provided in the ionic docs: http://jsfiddle.net/g6pdkfL8/
But basically:
<-- template for the modal window -->
<ion-modal-view>
<ion-content ng-controller="ModalController">
...
</ion-content>
<ion-modal-view>
There's no direct way of doing so in ionic. However, if you really want to have some common code being segregated at one place,
You can use services to do so. Here' how.
In your modal declaration, pass scope as null, also the modal declaration should move in a service.
app.service('utilsService', function($ionicModal) {
this.showModal = function() {
var service = this;
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: null,
controller: 'MyModalCotroller'
}).then(function(modal) {
service.modal = modal;
service.modal.show();
});
};
this.hideModal = function() {
this.modal.hide();
};
});
All your common methods will also move down into the same service.
Add the reference to this service into your controller's scope.
app.controller('indexController', function($scope, utilsService) {
$scope.utilsService = utilsService;
});
Now, you can call all the common methods from the view directly using this service.
e.g. <button ng-click="utilsService.hideModal()">Hide modal</button>
Based on this question and other needs I create a service that can be useful.
Anyway use the CodePen code, this updated, improved and it makes available the parameter 'options' of $ionicModal.
See this post: Ionic modal service or see in operation: CodePen
(function () {
'use strict';
var serviceId = 'appModalService';
angular.module('app').factory(serviceId, [
'$ionicModal', '$rootScope', '$q', '$injector', '$controller', appModalService
]);
function appModalService($ionicModal, $rootScope, $q, $injector, $controller) {
return {
show: show
}
function show(templateUrl, controller, parameters) {
// Grab the injector and create a new scope
var deferred = $q.defer(),
ctrlInstance,
modalScope = $rootScope.$new(),
thisScopeId = modalScope.$id;
$ionicModal.fromTemplateUrl(templateUrl, {
scope: modalScope,
animation: 'slide-in-up'
}).then(function (modal) {
modalScope.modal = modal;
modalScope.openModal = function () {
modalScope.modal.show();
};
modalScope.closeModal = function (result) {
deferred.resolve(result);
modalScope.modal.hide();
};
modalScope.$on('modal.hidden', function (thisModal) {
if (thisModal.currentScope) {
var modalScopeId = thisModal.currentScope.$id;
if (thisScopeId === modalScopeId) {
deferred.resolve(null);
_cleanup(thisModal.currentScope);
}
}
});
// Invoke the controller
var locals = { '$scope': modalScope, 'parameters': parameters };
var ctrlEval = _evalController(controller);
ctrlInstance = $controller(controller, locals);
if (ctrlEval.isControllerAs) {
ctrlInstance.openModal = modalScope.openModal;
ctrlInstance.closeModal = modalScope.closeModal;
}
modalScope.modal.show();
}, function (err) {
deferred.reject(err);
});
return deferred.promise;
}
function _cleanup(scope) {
scope.$destroy();
if (scope.modal) {
scope.modal.remove();
}
}
function _evalController(ctrlName) {
var result = {
isControllerAs: false,
controllerName: '',
propName: ''
};
var fragments = (ctrlName || '').trim().split(/\s+/);
result.isControllerAs = fragments.length === 3 && (fragments[1] || '').toLowerCase() === 'as';
if (result.isControllerAs) {
result.controllerName = fragments[0];
result.propName = fragments[2];
} else {
result.controllerName = ctrlName;
}
return result;
}
} // end
})();
Usage:
appModalService
.show('<templateUrl>', '<controllerName> or <controllerName as ..>', <parameters obj>)
.then(function(result) {
// result from modal controller: $scope.closeModal(result) or <as name here>.closeModal(result) [Only on template]
}, function(err) {
// error
});
You can use another service to centralize the configuration of all modals:
angular.module('app')
.factory('myModals', ['appModalService', function (appModalService){
var service = {
showLogin: showLogin,
showEditUser: showEditUser
};
function showLogin(userInfo){
// return promise resolved by '$scope.closeModal(data)'
// Use:
// myModals.showLogin(userParameters) // get this inject 'parameters' on 'loginModalCtrl'
// .then(function (result) {
// // result from closeModal parameter
// });
return appModalService.show('templates/modals/login.html', 'loginModalCtrl as vm', userInfo)
// or not 'as controller'
// return appModalService.show('templates/modals/login.html', 'loginModalCtrl', userInfo)
}
function showEditUser(address){
// return appModalService....
}
}]);
Create a directive to be used inside the modal and inside the directive you can assign the modal it's own controller and scope. If someone wants some example code I can put something up.
I was looking for a simple way to attach a controller to a modal instance and manage all modals with a single service. Also, I wanted the modal to have it's own isolated child scope. I wasn't satisfied with using ng-controller and I found other answers to be overly complicated to the point where you could easily loose track of scope and end up with circular or unidentifiable dependencies. I created the following service for my purposes.
You can pass an optional parentScope parameter to explicitly assign a parent scope to the created modal scope.
You could easily modify the instantiateModal method to accept $ionicModal options as an argument - I just didn't have the need for it.
BTW - I'm using the Webpack babel-loader for transpilation and the html-loader to load the templates. But, in it's simplest form, it's just a basic service.
/**
* nvModals
* #description A modal manager. Attaches a specified controller to an $ionicModal instance.
*/
import myModalTemplate from '../common/modals/my-modal.html';
import otherModalTemplate from '../common/modals/other-modal.html';
let nvModals = function (
$rootScope,
$controller,
$ionicModal
) {
var _self = this;
_self.methods = {
/**
* Instantiate and show a modal
*/
showMyModal: (parentScope) => {
var parentScope = parentScope || null;
_self.methods.instantiateModal('MyModalController', myModalTemplate, parentScope)
.show();
},
/**
* Instantiate and show another modal
*/
showOtherModal: (parentScope) => {
var parentScope = parentScope || null;
_self.methods.instantiateModal('OtherModalController', otherModalTemplate, parentScope)
.show();
},
/**
* Instantiate a new modal instance
*
* #param {object} controller Controller for your modal
* #param {string} template Template string
* #param {object} parentScope Optional parent scope for the modal scope
* #return {object} Modal instance
*/
instantiateModal: (controller, template, parentScope) => {
var modalScope;
if(parentScope) {
modalScope = $rootScope.$new(false, parentScope);
} else {
modalScope = $rootScope.$new(false);
}
$controller(controller, {
'$scope': modalScope
});
modalScope.modal = $ionicModal.fromTemplate(template, {
scope: modalScope,
animation: 'slide-in-up'
});
modalScope.$on('modal.hidden', (evt) => {
evt.targetScope.$destroy();
if (evt.targetScope.modal) {
evt.targetScope.modal.remove();
}
});
modalScope.hideModal = function () {
modalScope.modal.hide();
};
return modalScope.modal;
}
};
return _self.methods;
};
nvModals.$inject = [
'$rootScope',
'$controller',
'$ionicModal'
];
export default nvModals;
In your controller...
$scope.modals = nvModals;
In the associated template
ng-click="modals.showMyModal()"
In the modal template
ng-click="hideModal()"
Ok, I have seen a lot of different solutions to better handling Ionic modals because of the lack of a controller option or something similar.
After playing with React for a while I came up with another option, more declarative in my opinion. Is in ES6 and just a prototype but you can have an idea:
(function() {
'use strict';
#Inject('$scope', '$ionicModal', '$transclude', '$rootScope')
class Modal {
constructor() {
let { animation, focusFirstInput, backdropClickToClose, hardwareBackButtonClose } = this;
$transclude((clone, scope) => {
let modal = this.createModalAndAppendClone({
scope,
animation,
focusFirstInput,
backdropClickToClose,
hardwareBackButtonClose
}, clone);
this.setupScopeListeners(modal.scope);
this.createIsOpenWatcher();
this.addOnDestroyListener();
this.emitOnSetupEvent(modal.scope);
});
}
setupScopeListeners(scope) {
scope.$on('modal.shown', this.onShown);
scope.$on('modal.hidden', this.onHidden);
scope.$on('modal.removed', this.onRemoved);
}
addOnDestroyListener() {
this.$scope.$on('$destroy', () => {
this.removeModal();
});
}
createIsOpenWatcher() {
this.isOpenWatcher = this.$scope.$watch(() => this.isOpen, () => {
if (this.isOpen) {
this.modal.show();
} else {
this.modal.hide();
}
});
}
emitOnSetupEvent(scope) {
this.onSetup({
$scope: scope,
$removeModal: this.removeModal.bind(this)
});
}
createModalAndAppendClone({
scope = this.$rootScope.$new(true),
animation = 'slide-in-up',
focusFirstInput = false,
backdropClickToClose = true,
hardwareBackButtonClose = true
}, clone) {
let options = {
scope,
animation,
focusFirstInput,
backdropClickToClose,
hardwareBackButtonClose
}
this.modal = this.$ionicModal.fromTemplate('<ion-modal-view></ion-modal-view>', options);
let $modalEl = angular.element(this.modal.modalEl);
$modalEl.append(clone);
return this.modal;
}
removeModal() {
this.modal.remove();
this.isOpenWatcher();
}
}
function modal() {
return {
restrict: 'E',
transclude: true,
scope: {
'onShown': '&',
'onHidden': '&',
'onRemoved': '&',
'onSetup': '&',
'isOpen': '=',
'animation': '#',
'focusFirstInput': '=',
'backdropClickToClose': '=',
'hardwareBackButtonClose': '='
},
controller: Modal,
bindToController: true,
controllerAs: 'vm'
}
}
angular
.module('flight')
.directive('modal', modal);
})();
And then you can use it like this:
<modal is-open="vm.isOpen" on-shown="vm.onShown()" on-hidden="vm.onHidden()" on-removed="vm.onRemoved()" on-setup="vm.onSetup($scope, $removeModal)">
<div class="bar bar-header bar-clear">
<div class="button-header">
<button class="button button-positive button-clear button-icon ion-close-round button-header icon" ng-click="vm.closeModal()"></button>
</div>
</div>
<ion-content class="has-header">
<create-flight-form on-submit="vm.submit()"></create-flight-form>
</ion-content>
</modal>
You open and close the modal with a boolean value bind to is-open and then register callbacks for the different events.
I just noticed that Ext.get('myElement').getAttribute('class') doesn't work with IE8-. Does anyone has an elegant alternative (ExtJS 4.1.1 native or patch prefered)? Maybe this feature is hidden somewhere in the framework?
Edit
Here is the context. I have temporarily fixed the issue like this :
action.getAttribute('class') || action.dom.className
View (grid) :
{
xtype: 'actioncolumn',
items: [{
icon: '/images/edit.png',
iconCls: 'action-edit'
}, {
icon: '/images/delete.png',
iconCls: 'action-delete'
}]
}
Controller :
init: function () {
this.control({
'grid actioncolumn': {
click: function (a, b, c, d, ev, record) {
var action = Ext.get(ev.target);
if (action.is('img')) {
action = action.getAttribute('class') || action.dom.className;
action = action.match(/action-(.+)/)[1];
this[action + 'Action'](record);
}
}
}
});
},
editAction: function (record) {
// ...
},
deleteAction: function (record) {
// ...
}
Drop # from the node id and it'll probably work.
UPDATE: I'm still not sure what exactly you're trying to do. Ext.get returns Ext.dom.Element object, which wraps native element and provides a certain level of abstraction from DOM but still is pretty much low-level tool. Since older IE doesn't support 'class' attribute you'll have to call getAttribute('className') to get the result.
Or you can resort to using standard convenience methods like hasCls and getStyle for checking particular classes and styles on an element. To find elements with particular class there's query method. All in all I fail to see why exactly you would need to get the list of all classes defined on an element.
UPDATE 2: OK, now I get what you need. Your code is way too complex, it can be simplified like this:
CSS:
.action-edit, .action-delete {
width: 16px; /* Or whatever fits your bill */
height: 16px;
}
.action-edit {
background-image: url('/images/edit.png');
}
.action-delete {
background-image: url('/images/delete.png');
}
View:
{
xtype: 'actioncolumn',
items: [{
iconCls: 'action-edit',
action: 'edit'
}, {
iconCls: 'action-delete',
action: 'delete'
}]
}
Controller:
init: function() {
this.control({
'grid actioncolumn': {
click: function(a, b, c, d, ev, record) {
var target = Ext.get(ev.target);
if (target && target.action) {
this[target.action + 'Action'].call(this, record);
}
}
}
});
}
Or it can be done in more officially supported way:
View:
{
xtype: 'actioncolumn',
items: [{
iconCls: 'action-edit',
handler: function(grid, rowIndex) {
this.fireEvent('editAction', grid.getStore().getAt(rowIndex));
}
}, {
iconCls: 'action-delete',
handler: function(grid, rowIndex) {
this.fireEvent('deleteAction', grid.getStore().getAt(rowIndex));
}
}];
}
Controller:
init: function() {
this.control({
'grid actioncolumn': {
editAction: this.editAction,
deleteAction: this.deleteAction
}
});
}
Obviously the view event handling code can be further abstracted, but the main idea here is that you shouldn't be afraid of hiding view complexities Controller has no need to know about.