bind mouseout with jquery in ie7 - internet-explorer-7

I need to rebind mouseout event in jquery because when mouse go to a child of main div (what i have binded the mouseout event), mouseout event is called and I don't want it. So i do this:
$('.div-hidden').live('mouseout', function (event) {
e = event.toElement || event.relatedTarget;
if (e.parentNode.parentNode == this || e == this || e.parentNode == this) {
return;
}
if ($(this).parent().css('overflow') == "visible") {
var parent_height = parseInt($(this).parent().parent().css('height').substr(0, $(this).css('height').length), 10);
$(this).parent().animate({
top: (parent_height - 40) + "px"
}, 500, function () {
$(this).css('overflow', 'hidden');
});
}
});
This works good in ie8/9 and others browser, but not in ie7. I also tried to change live() with bind() but it doesn't work. How can I do?

Seems you want mouseleave event instead:
$('.div-hidden').live('mouseleave', function (event) {
if ($(this).parent().css('overflow') == "visible") {
var parent_height = parseInt($(this).parent().parent().css('height').substr(0, $(this).css('height').length), 10);
$(this).parent().animate({
top: (parent_height - 40) + "px"
}, 500, function () {
$(this).css('overflow', 'hidden');
});
}
});
You should not use .live unless your jQuery version is < 1.4.2 or something.

Maybe you're better to use mouseenter / mouseleave events in this case?

Related

how to create custom editor provider in ignite ui grid with angular js

I am using Ignite UI grid directive with angular js.
In that I am creating custom editor provider by extending $.ig.EditorProvider
and using that editor in html markup as
<column-setting column-key="comments" editor-provider="new $.ig.EditorProviderNumber()">
</column-setting>
but when I edit grid its showing error
provider.createEditor is not a function
plz help me
Written this way the "editor-provider" value will be evaluated as string. In order for the expression to be parsed to an object you need to enclose it in {{}} (double curly braces). However the statement "new $.ig.EditorProviderNumber()" will not be parsed by the Angular 1 expression parser, so you need to use a scope function to create the object.
Here is the code:
// This editor provider demonstrates how to wrap HTML 5 number INPUT into editor provider for the igGridUpdating
$.ig.EditorProviderNumber = $.ig.EditorProviderNumber || $.ig.EditorProvider.extend({
// initialize the editor
createEditor: function (callbacks, key, editorOptions, tabIndex, format, element) {
element = element || $('<input type="number" />');
/* call parent createEditor */
this._super(callbacks, key, editorOptions, tabIndex, format, element);
element.on("keydown", $.proxy(this.keyDown, this));
element.on("change", $.proxy(this.change, this));
this.editor = {};
this.editor.element = element;
return element;
},
keyDown: function(evt) {
var ui = {};
ui.owner = this.editor.element;
ui.owner.element = this.editor.element;
this.callbacks.keyDown(evt, ui, this.columnKey);
// enable "Done" button only for numeric character
if ((evt.keyCode >= 48 && evt.keyCode <= 57) || (evt.keyCode >= 96 && evt.keyCode <= 105)) {
this.callbacks.textChanged(evt, ui, this.columnKey);
}
},
change: function (evt) {
var ui = {};
ui.owner = this.editor.element;
ui.owner.element = this.editor.element;
this.callbacks.textChanged(evt, ui, this.columnKey);
},
// get editor value
getValue: function () {
return parseFloat(this.editor.element.val());
},
// set editor value
setValue: function (val) {
return this.editor.element.val(val || 0);
},
// size the editor into the TD cell
setSize: function (width, height) {
this.editor.element.css({
width: width - 2,
height: height - 2,
borderWidth: "1px",
backgroundPositionY: "9px"
});
},
// attach for the error events
attachErrorEvents: function (errorShowing, errorShown, errorHidden) {
// implement error logic here
},
// focus the editor
setFocus: function () {
this.editor.element.select();
},
// validate the editor
validator: function () {
// no validator
return null;
},
// destroy the editor
destroy: function () {
this.editor.remove();
}
});
sampleApp.controller('sampleAppCtrl', function ($scope) {
$scope.getProvider = function () {return new $.ig.EditorProviderNumber()};
});
<column-setting column-key="ProductNumber" editor-provider="{{getProvider()}}"></column-setting>

How do I get clientHeight of parent element when `ng-cloak` is active

I have the following in the linker for my directive....
pre: function preLink($scope, e) {
var element = d3.select(e[0]);
var height = element.node().parentNode.clientHeight;
element
.style({
"border": "7px solid black",
"min-height": height+"px",
"background-image" : "url('http://s3.amazonaws.com/dostuff-production/property_assets/23107/yellow-stripes.png')"
});
element.select(".board")
.style("transform", function(d){
var ch = d3.select(this).node().clientHeight;
return "translate("+0+"px, "+(height/2-ch/2)+"px)"
})
}
And then in my code I have
<jg-body ng-cloak>
The problem is that element.node().parentNode.clientHeight; is 0 thanks to the ng-cloak. Is there a way to defer the link function till after the ng-cloak is removed?
Update
Based on feedback I tried this...
compile: function compile() {
return {
pre: function preLink($scope, e) {
var element = d3.select(e[0]);
$timeout(function() {
var height = element.node().parentNode.clientHeight;
element
.style({
"border": "7px solid black",
"min-height": height + "px",
"background-image": "url('http://s3.amazonaws.com/dostuff-production/property_assets/23107/yellow-stripes.png')"
});
element.select(".board")
.style("transform", function (d) {
var ch = d3.select(this).node().clientHeight;
return "translate(" + 0 + "px, " + (height / 2 - ch / 2) + "px)"
})
})
}
}
}
However, var height = element.node().parentNode.clientHeight; is still 0 and removing ng-cloak fixes it. I created an example plnker here
Would a $timeout or something work?
Yes , it should. Also note that you are checking the height inside the pre link which runs before directive will be compiled. Before it is compiled it will have no content
You should move the code to post link and probably use $timeout there depending on what jg-body templating does. Also if it relies on asynchronous data to render and then get height you have another issue to deal with that would need more code shown to sort out

Angular ui-bootstrap typeahead suggestion - scroll

According to this link :
up/down arrow key issue with typeahead control (angular bootstrap UI)
i have added these line in my js:
.directive('shouldFocus', function(){
return {
restrict: 'A',
link: function(scope,element,attrs){
scope.$watch(attrs.shouldFocus,function(newVal,oldVal){
element[0].scrollIntoView(false);
});
}
};
})
while scrolling, we get some more disturb, scroll was not smoothy.
Before adding this code, scroll was normal and smoothy.
Please anyone help me?
Hi here is another code only for keyup event to adjust the scroll height while up/down keypress
you need to add a function only to keyup in the typeahead directive in angular ui
search directive('typeahead' in the angular ui js file
find fireRecalculating function before it paste the following function
function makeSureVisible(){
$timeout(function(){
$el = popUpEl.find('.active');
if($el.length>0)
{
var elTop, elBottom, nodeScrollTop, nodeHeight;
elTop = $el.position().top;
console.log(elTop);
elBottom = elTop + $el.outerHeight(true);
nodeScrollTop = popUpEl.scrollTop();
nodeHeight = popUpEl.height() + parseInt(popUpEl.css("paddingTop"), 10) + parseInt(popUpEl.css("paddingBottom"), 10);
if (elTop < 0) {
popUpEl.scrollTop(nodeScrollTop + elTop);
} else if (nodeHeight < elBottom) {
popUpEl.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
}
}
});
}
now find keyup function attached. call the above function
element.bind('keydown', function(evt) {
//typeahead is open and an "interesting" key was pressed
if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
return;
}
// if there's nothing selected (i.e. focusFirst) and enter or tab is hit, clear the results
if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) {
resetMatches();
scope.$digest();
return;
}
evt.preventDefault();
if (evt.which === 40) {
scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
scope.$digest();
makeSureVisible();
} else if (evt.which === 38) {
scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
scope.$digest();
makeSureVisible();
} else if (evt.which === 13 || evt.which === 9) {
scope.$apply(function () {
scope.select(scope.activeIdx);
});
} else if (evt.which === 27) {
evt.stopPropagation();
resetMatches();
scope.$digest();
}
});
function makeSureVisible() {
$timeout(function () {
$el = popUpEl[0].querySelector('.active');
if ($el) {
var elTop, elBottom, nodeScrollTop, nodeHeight;
elTop = $el.offsetTop;
elBottom = elTop + $el.offsetHeight;
nodeScrollTop = popUpEl[0].scrollTop;
nodeHeight = popUpEl[0].offsetHeight - (parseInt(window.getComputedStyle(popUpEl[0], null).getPropertyValue('padding-top')) + parseInt(window.getComputedStyle(popUpEl[0], null).getPropertyValue('padding-bottom')));
if (elTop < nodeScrollTop) {
popUpEl[0].scrollTop = elTop;
} else if (nodeHeight < elBottom) {
popUpEl[0].scrollTop = nodeScrollTop + elBottom - nodeHeight;
}
}
});
}
I bumped into the same issue with latest version of angular bootstrap 0.14.3 as of 27/11/2015.
Comments:
I placed the function in the element.bind("keydown") since it didn't work where you suggested. (function wasn't in proper scope and was undefined)
The first "if" wasn't triggered for me so i changed the logic a bit. When user reaches the end the dropdown scrolls to top properly in my case.
Modified it to work for plain javascript.
Thank you for your solution!
I had previously resolved this issue using the "shouldFocus" directive but I had to make more tweaks to get this to work. Perhaps this version will work for you.
.directive('shouldFocus', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(attrs.shouldFocus, function (newVal, oldVal) {
if (newVal && element.prop("class").indexOf("active")) {
var par = element.parent("ul");
var cellHeight = element.children().innerHeight();
var maxHeight = par.height();
var startIndex = Math.floor(maxHeight / cellHeight);
if (scope.$index > startIndex) {
var scroll = (scope.$index - startIndex) * cellHeight;
par.scrollTop(scroll);
}
if (scope.$index === 0) {
par.scrollTop(0);
}
}
});
}
}
})
Here is the modified template for those who don't know where to add the directive:
angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template/typeahead/typeahead-popup.html",
"<ul class=\"dropdown-menu\" ng-show=\"isOpen() && !moveInProgress\" ng-style=\"{top: position().top+'px', left: position().left+'px'}\" style=\"display: block;\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
" <li ng-repeat=\"match in matches track by $index\" should-focus=\"isActive($index)\" ng-class=\"{active: isActive($index) }\" ng-click=\"selectMatch($index)\" role=\"option\" id=\"{{::match.id}}\">\n" +
" <div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
" </li>\n" +
"</ul>\n" +
"");
}]);

Assign click events to D3 chart elements using Backbone.js

I want to bind click events to points created by a chart instantiated by a Backbone View, but events and delegateEvents aren't working (ie, no event is fired on clicking '.point' elements):
// View
var ScatterView = Backbone.View.extend({
defaults:{
// height, width, etc.
},
events:{
'click .point':'clickFunction'
},
clickFunction:function() {
console.log('clicked')
},
initialize:function(options) {
this.options = _.extend({}, this.defaults, options)
this.render()
},
render:function() {
var that = this
this.chart = new Scatter({
container:that.el.id,
// pass parameters: width, height, etc.
})
this.delegateEvents()
}
})
// Scatter function
var Scatter = function(settings) {
this.settings = settings
this.build()
}
Scatter.prototype.build = function() {
// Bind points
this.div = d3.select('#' + settings.container).append('div').attr('id', settings.id).attr('class', 'chart')
this.g = this.div.append('g')
this.points = this.g.selectAll('.point')
.data(this.data, function(d) {return d.id})
.enter().append('circle')
.attr('cx', function(d) {return that.xScale(d.x)})
.attr('cy', function(d) {return that.yScale(d.y)})
.attr('r', that.settings.radius)
.attr('class', 'point')
}
// instantiate view
var sv = new ScatterView({model:sm, el:'#main', chartid:'scatter-' + d, textid:'text-' + d})
You need to set an el property, for example:
var ScatterView = Backbone.View.extend({
el: '#chartContainer', ...
});
Try this:
events:{
"click [class~=point]" : "clickFunction"
}
The problem is that Backbone uses jQuery event binding under the covers, but you're trying to set click events on SVG elements. Without additional plugins, jQuery won't reliably select SVG elements, so there's no way it can bind events to them.

jQuery UI Autocomplete: set active item

I am trying to micmic teh behaviour of a simple HTML SELECT element with jQuery Ui Autocomplete.
Is it possible to set the active item (move focus) on the open event? Basically, I am trying to mimic the selected="selected" option from a html select element - if the value in the field matches with one from the list, make that list item 'selected'.
Here's a jsfiddle of what you'e looking for: http://jsfiddle.net/fordlover49/NUWJr/
Basically, took the combobox example from jquery's website, and changed the renderItem functionality. In the example off of jqueryui.com's site, change:
input.data("autocomplete")._renderItem = function(ul, item) {
return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul);
};
To:
input.data("autocomplete")._renderItem = function(ul, item) {
$item = $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>");
if (this.element.val() === item.value) {
$item.addClass('ui-state-hover');
}
return $item.appendTo(ul);
};
You can use the focus event to add/remove the active class. I like it more than the other ._renderItem code on this thread.
[...previous autocomplete options]
focus: function( event, ui ) {
// Remove the hover class from all results
$( 'li', ui.currentTarget ).removeClass('ui-state-hover');
// Add it back in for results
$( 'li',ui.currentTarget ).filter(function(index, element) {
// Only where the element text is the same as the response item label
return $(element).text() === ui.item.label;
}).addClass('ui-state-hover');
},
[next autocomplete options...]
Well, I finally figured out the answer with the help of a friend.
$('input[data-field=vat_rate]', view.el).autocomplete({
source: function (request, response) {
response(your_source_array);
},
minLength: 0,
open: function (event, ui) {
var term = ui.item.value;
if (typeof term !== 'undefined') {
$(this).data("autocomplete").menu.activate(new $.Event("mouseover"), $('li[data-id=' + term + ']'));
}
}
}).click(function () {
if ($(this).autocomplete('widget').is(':visible')) {
$(this).autocomplete('close');
} else {
$(this).autocomplete('search');
}
}).data("autocomplete")._renderItem = function (ul, item) {
var listItem = $("<li></li>")
.data("item.autocomplete", item)
.attr("data-id", item.id)
.append('<a>' + item.label + '</a>')
.appendTo(ul);
};
Here's the JSBin for it: http://jsbin.com/unibod/2/edit#javascript
Works perfect! :)

Resources