I am using Bootstrap-select in my project. Is it possible to add a callback when Select has been opened? Code below does not work.
var sp = $.fn.selectpicker.constructor.prototype.show;
$.fn.selectpicker.constructor.prototype.show = function () {
sp.call(this);
if (this.options.callback) {
//console.log('is callback!');
this.options.callback();
}
};
$('.selectpicker-state').selectpicker({
title: null,
callback: function() {
alert('show!');
}
});
You can use the bootstrap dropdown event shown
http://getbootstrap.com/javascript/#dropdowns and see the Events section
$('#myDropdown').on('show.bs.dropdown', function () {
// do something…
})
Related
I'm trying to upgrade our app from a really old version to the latest (v16). Since they have deprecated the old way of cell and header renders I'm trying to wrap my head around using scope and Angular compilation.
The ag-grid documentation states: You will then need to manage creating and destroying child scopes yourself inside the init() and destroy() methods.
angularCompileRows, angularCompileFilters and angularCompileHeaders are not supported within Components.
I tried to create a cell render like this:
function MyCellRenderer() {
}
MyCellRenderer.prototype.init = function (params) {
$scope.myMessage = 'Hi Scott';
var compiled = $compile('<p ng-bind="myMessage"></p>')($scope);
this.eGui = document.createElement('span');
this.eGui.innerHTML = compiled.html();
};
MyCellRenderer.prototype.getGui = function () {
return this.eGui;
};
However this doesn't work. Any thoughts?
I was able to get this to work, but I don't like that I need to wrap around a $timeout. I had to do this because a digest was already in progress:
function MyCellRendererSimple() {
}
MyCellRendererSimple.prototype.init = function (params) {
console.log('init Called');
this.eGui = document.createElement('span');
};
MyCellRendererSimple.prototype.getGui = function () {
var self = this;
$timeout(function() {
var compiled = $compile('<nice-checkbox checkbox-id="checkbox-2" ng-model="checkboxModal1"></nice-checkbox>')($scope);
$scope.$digest();
self.eGui.appendChild(compiled[0]);
});
return self.eGui;
};
I need to implement toggle functionality for the widget. When the user clicks on the minimization button then widget should shrink and expand when click on maximize button respectively.
I'm trying to achieve this functionality with below piece of code.
Functionality working as expected but it is registering the event multiple times(I'm emitting the event and catching in the filterTemplate directive).
How can we stop registering the event multiple times ?
Or
Is there anyway to like compiling once and on toggle button bind the template/directive to DOM and to make it work rest of the functionality .
So could you please help me to fix this.
function bindFilterTemplate(minimize) {
if ($scope.item && !minimize) {
if ($scope.item.filterTemplate) { // filter template is custom
// directive like this
// "<widget></widget>"
$timeout(function () {
var filterElement = angular.element($scope.item.filterTemplate);
var filterBody = element.find('.cls-filter-body');
filterElement.appendTo(filterBody);
$compile(filterElement)($scope); // Compiling with
// current scope on every time when user click on
// the minimization button.
});
}
} else {
$timeout(function () {
element.find('.cls-filter-body').empty();
});
}
}
bindFilterTemplate();
// Directive
app.directive('widget', function () {
return {
restrict: 'E',
controller: 'widgetController',
link: function ($scope, elem) {
// Some code
}
};
});
// Controller
app.controller('widgetController', function ($scope) {
// This event emitting from parent directive
// On every compile, the event is registering with scope.
// So it is triggering multiple times.
$scope.$on('evt.filer', function ($evt) {
// Server call
});
});
I fixed this issue by creating new scope with $scope.$new().
When user minimizes the widget destroying the scope.
Please let me know if you have any other solution to fix this.
function bindFilterTemplate(minimize) {
// Creating the new scope.
$scope.newChildScope = $scope.$new();
if ($scope.item && !minimize) {
if ($scope.item.filterTemplate) {
$timeout(function () {
var filterElement = angular.element($scope.item.filterTemplate);
var filterBody = element.find('.cls-filter-body');
filterElement.appendTo(filterBody);
$compile(filterElement)($scope.newChildScope);
});
}
} else {
$timeout(function () {
if ($scope.newChildScope) {
// Destroying the new scope
$scope.newChildScope.$destroy();
}
element.find('.cls-filter-body').empty();
});
}
}
I'm using the Angular UI bootstrap modal and I ran into a bit of a problem.
I want to call a function when the bootstrap modal dismiss animation is finished. The code block below will call the cancel() function as soon as the modal starts to be dismissed - and NOT when the modal dismiss animation has finished.
Angular UI does not use events, so there is no 'hidden.bs.modal' event being fired (at least, not to my knowledge).
var instance = $modal.open({...});
instance.result.then(function(data) {
return success(data);
}, function() {
return cancel();
})
The cancel() block immediately runs when the modal starts to close. I need code to execute when the closing animation for the Bootstrap modal finishes.
How can I achieve this with angular UI?
Component for reference:
https://angular-ui.github.io/bootstrap/#/modal
Thanks!
A little late but hope it still helps! You can hijack the uib-modal-window directive and check when its scope gets destroyed (it is an isolated scope directive). The scope is destroyed when the modal is finally removed from the document. I would also use a service to encapsulate the functionality:
Service
app.service('Modals', function ($uibModal, $q) {
var service = this,
// Unique class prefix
WINDOW_CLASS_PREFIX = 'modal-window-interceptor-',
// Map to save created modal instances (key is unique class)
openedWindows = {};
this.open = function (options) {
// create unique class
var windowClass = _.uniqueId(WINDOW_CLASS_PREFIX);
// check if we already have a defined class
if (options.windowClass) {
options.windowClass += ' ' + windowClass;
} else {
options.windowClass = windowClass;
}
// create new modal instance
var instance = $uibModal.open(options);
// attach a new promise which will be resolved when the modal is removed
var removedDeferred = $q.defer();
instance.removed = removedDeferred.promise;
// remember instance in internal map
openedWindows[windowClass] = {
instance: instance,
removedDeferred: removedDeferred
};
return instance;
};
this.afterRemove = function (modalElement) {
// get the unique window class assigned to the modal
var windowClass = _.find(_.keys(openedWindows), function (windowClass) {
return modalElement.hasClass(windowClass);
});
// check if we have found a valid class
if (!windowClass || !openedWindows[windowClass]) {
return;
}
// get the deferred object, resolve and clean up
var removedDeferred = openedWindows[windowClass].removedDeferred;
removedDeferred.resolve();
delete openedWindows[windowClass];
};
return this;
});
Directive
app.directive('uibModalWindow', function (Modals) {
return {
link: function (scope, element) {
scope.$on('$destroy', function () {
Modals.afterRemove(element);
});
}
}
});
And use it in your controller as follows:
app.controller('MainCtrl', function ($scope, Modals) {
$scope.openModal = function () {
var instance = Modals.open({
template: '<div class="modal-body">Close Me</div>' +
'<div class="modal-footer"><a class="btn btn-default" ng-click="$close()">Close</a></div>'
});
instance.result.finally(function () {
alert('result');
});
instance.removed.then(function () {
alert('closed');
});
};
});
I also wrote a blog post about it here.
I am not very familiar with the CKEDITOR API yet and now I got stuck trying to find the way to create placeholders inside of the CKEDITOR editable area.The expected behaviour for the placeholder - to dissappear on user interaction with it, allowing to edit the content instead.
I know that there is already a placeholder plugin (http://ckeditor.com/addon/placeholder) but its behaviour is not what I am looking for.
To be more specific, the question is: is it possible to subscribe for some events on the particular element inside of the CKEDITOR?
Working in the angular context I am able to compile my html before it is passed to the CKEDITOR ng-model
$scope.html = $compile('<div><span text-placeholder >Placeholder</span></div>')($scope).html();
But then I fail trying to set click events inside of the directive:
.directive('textPlaceholder', [ function () {
return {
restrict: 'A',
link: function ($scope, $element) {
//THIS DOES NOT WORK UNFORTUNATELY
$element.on('click', function () {
console.log('clicked');
})
}
}
}])
Any thoughts?
UPDATE: For now I came up with the solution to implement simple plugin and then reference it in the CKEDITOR config:
(function () {
CKEDITOR.plugins.add('text-placeholder', {
init: function (editor) {
editor.on('key', function (evt) {
var el = $(CKEDITOR.instances.editor1.getSelection().getNative().baseNode.parentElement);
if (el.hasClass('text-placeholder')) {
el.remove();
}
});
}
});
})();
Looks ugly for me. Any feedback is appreciated.
This seems to be a final Solution:
CKEDITOR.plugins.add('text-placeholder', {
init: function (editor) {
editor.on('contentDom', function () {
var editable = editor.editable();
editable.attachListener(editable, 'click', function (event) {
var $placeholder = $(event.data.$.target).closest('.text-placeholder');
if ($placeholder.length > 0) {
var selection = editor.getSelection();
selection.selectElement(selection.getStartElement());
}
});
});
}
});
This applies the selection on the element with "text-placeholder" class when user focuses it inside of the editable area
Update:
See example
You inspired me to write one myself, using the above example as a starting point. In my use case I wanted to take placeholder text from an attribute on the editor -- data-placeholder -- and display it in the editor. When the editor gets focus, the placeholder text disappears. When the editor blurs -- if no user content has been entered -- the placeholder text is displayed again. Additionally, I set a data-placeholder-showing attribute so that I can, for example, use CSS to make the placeholder text gray. Here's my code:
CKEDITOR.plugins.add('text-placeholder', {
init: function (editor) {
var placeholder = editor.element.getAttribute('data-placeholder');
editor.on('contentDom', function () {
if (placeholder) {
editor.setData(placeholder);
editor.element.setAttribute('data-placeholder-showing', true);
}
});
editor.on('focus', function() {
if (editor.getData() === placeholder) {
editor.element.setAttribute('data-placeholder-showing', false);
editor.setData('');
}
});
editor.on('blur', function() {
if (placeholder && editor.getData().length === 0) {
editor.element.setAttribute('data-placeholder-showing', true);
editor.setData(placeholder);
}
});
}
});
I was able to simulate click events using React test utils, but I couldn't simulate mouseEnter events
I added sample component and it tests in jsfiddle to show this problem
http://jsfiddle.net/kirana/Uf4e2/2/
var Events = React.createClass({
getInitialState: function () {
return {
event: ''
};
},
clickHandler: function () {
this.setState({
event: 'click'
});
},
mouseEnterHandler: function () {
this.setState({
event: 'mouseenter'
});
},
render: function () {
return React.DOM.div(null, React.DOM.button({
ref: 'button',
onClick: this.clickHandler,
onMouseEnter: this.mouseEnterHandler
}, 'click or mouseenter'), React.DOM.div(null, this.state.event));
}
});
var ReactTestUtils = React.addons.TestUtils;
describe('Events', function () {
it('should have click event state', function (done) {
var events = Events();
ReactTestUtils.renderIntoDocument(events);
ReactTestUtils.Simulate.click(events.refs.button.getDOMNode());
events.state.event.should.equal('click');
done();
});
// This test is failing
it('should have mouseenter event state', function (done) {
var events = Events();
ReactTestUtils.renderIntoDocument(events);
ReactTestUtils.Simulate.mouseEnter(events.refs.button.getDOMNode());
events.state.event.should.equal('mouseenter');
done();
});
});
I couldn't figure out what I am missing to simulate mouseEnter.
Currently mouseenter/mouseleave can't be simulated directly using ReactTestUtils; see this open issue: Simulate.mouseEnter and Simulate.mouseLeave not working.
As a workaround for now, you can use SimulateNative.mouseOver and SimulateNative.mouseOut (making sure to specify relatedTarget appropriately on each) and together they will cause React to fire onMouseEnter and onMouseLeave events.
This answer is a bit different now as the mouseOver event works in React since v0.11.1 - see here
That means you can now use
ReactTestUtils.Simulate.mouseEnter(events.refs.button.getDOMNode());
just as you tried in your example.