One of the nice things about the jQuery UI Dialog is that it has an option for Buttons, which automatically positions them correctly. I just wonder: Can I somehow place elements next to the buttons? I have a little Ajax-Loader gif that I would like to display in the lower left corner of the dialog, while the buttons stay at the lower right?
I know I can just remove the buttons and create them manually in HTML, but as jQuery takes care of positioning and styling already for me, I'd like to keep that functionality if it makes sense.
$("#newProjectDialog").dialog({
bgiframe: true,
resizable: false,
width: 400,
modal: true,
overlay: {
backgroundColor: '#000',
opacity: 0.5
},
buttons: {
'Create': function() {
$("#ajax-loader").show();
// Make the Ajax Call and whatever else is needed
$(this).dialog('destroy');
},
Cancel: function() {
$(this).dialog('destroy');
}
}
});
All you basically need to do is
//depending on what #ajax-loader is you maybe need to style it (float:left, ...)
$("#ajax-loader").clone(true).appendTo("div.ui-dialog-buttonpane").show();
Below a fancier version with a few considerations incorporated.
I imagine #ajax-loader to look similar to this
<div id='ajax-loader'><img src='loader.gif' /><span>loading...</span></div>
or just this
<img id='ajax-loader' src='loader.gif' />
javascript can look like this
...
'Create': function() {
var btnpane = $("div.ui-dialog-buttonpane");
//prevent bad things if create is clicked multiple times
var there = btnpane.find("#ajax-loader").size() > 0;
if(!there) {
$("#ajax-loader").clone(true).appendTo(btnpane).show();
// Make the Ajax Call and whatever else is needed
// if ajax call fails maybe add $("#ajax-loader", btnpane).remove();
$(this).dialog('destroy');
}
},
...
A note
You should call .dialog('destroy') in the complete event of the ajax request else the dialog may get destroyed before the ajax request finished and the user may not even see the "loader".
How about just inserting your spinner before the first ui-dialog-button?
buttons: {
'Create' : function() {
$('<img src="spinner.gif" style="float: left;" />').insertBefore('.ui-dialog-buttonpane > button:first');
...ajax stuff...
$(this).dialog('destroy');
}
}
The best way to do this, is to create another button, make it totally transparent with no border, and add the animated gif as its background image. By using another button, you can easily locate its position relative to all your other buttons.
First, to be able to style buttons more, you need to create them with one level higher of definition. So instead of:
buttons: {
'Create': function() {
$("#ajax-loader").show();
// Make the Ajax Call and whatever else is needed
$(this).dialog('destroy');
},
Cancel: function() {
$(this).dialog('destroy');
}
}
Do it like this (notice square brackets and one more level of indent):
buttons: [
{
id: 'create-button',
class: 'create-button-class',
text: 'Create',
click: function() {
$("#ajax-loader").show();
// Make the Ajax Call and whatever else is needed
$(this).dialog('destroy');
}
},
text: 'Cancel',
click: function() {
$(this).dialog('destroy');
}
}
]
You can assign an id and class to each button or not. If you assign either id and/or class, then you can apply CSS styling to it.
<style>
.create-button-class{
height:50px;
width:50px;
left:-300px; /* Pushes it left, change value for desired location. */
}
.ui-dialog .ui-dialog-buttonpane #create-button {
color: transparent; /* no inner color and also hides text */
border: none; /* removes border */
background-image:url(images/spinner-gif-25px.gif); /*replaces default image */
background-size: 50px;
background-repeat: no-repeat;
}
</style>
If you like, create a normal additional button and use CSS property left to push it as far left in the button panel as you like, before making it transparent and no border.
Related
We are working with software supplied by a third party, and we are not allowed to modify it, can use only overrides.
I would like to create a new button and overlay it on top of a text input so that they are close together.
I'm having trouble getting the overlay to align, instead it appears top left on the screen. So of course it doesn't align to the text input. Sample code is below, in this case implemented in the view initComponent override after this.callParent([]); is called.
var viewport = Ext.ComponentQuery.query('viewport')[0];
var overlay = viewport.add({
xtype: 'panel',
fullscreen: true,
left: 0,
top: 0,
width: 120,
height: 40,
items:[{
xtype: 'button',
text: 'Find Address',
handler: function() {
alert('Got it!');
}
}],
styleHtmlContent: true
});
var textField = this.query('*[itemId=textField]')[0];
overlay.showBy(textField, 'c-c?');
I've tried using floating: true and lots of other approaches.
Once I get it to position properly, is there a way to have the button respond to tab order correctly? That is, tab out of the text field, then have the button get focus?
As I understand from your question, you have trouble with setting position to a component. If it is the problem, you can set xy coordinate. Look at this fiddle:
https://fiddle.sencha.com/#fiddle/tpl
viewport.down('#idOverlay').setXY([150, 140]);
Edit:
Ext.define('OverriddenViewport', {
override: 'ExampleViewPort',
initComponent: function() {
// Set up first
this.callParent([]);
this.add(overlay);
this.addListener('afterrender', function(viewport) {
viewport.down('#idOverlay').setXY([220,50]);
viewport.down('#idButton').addListener('blur', function(button) {
viewport.down('#idTextfield').focus();
console.log('textfield is focussed');
});
viewport.down('#idTextfield').addListener('blur', function(button) {
viewport.down('#idButton').focus();
console.log('button is focussed');
});
});
}
});
If you can access the source (just to look around) you maybe can create an override of the corresponding class. Create a override, and copy all of the code of the class (form?) into your override.
Here some additional info about creating overrides in ExtJs:
http://moduscreate.com/writing-ext-js-overrides/
https://sencha.guru/2014/12/04/abstract-vs-override/
In your override create a trigger (on the field you want to expand) with your functionality:
{
fieldLabel: 'My Custom Field',
triggers: {
foo: {
cls: 'my-foo-trigger',
handler: function() {
console.log('foo trigger clicked');
}
}
}
}
I'm using highslide in conjunction with highcharts and I want to modify the close button, more specifically, I want to call an additional function when a user clicks that "X" button.
When I inspect that "X" button, I get this in my console
<span>Close</span>
I want to do something like this
<span>Close</span>
But I am unable to find where the code for that is located.
I have tried adding this to my header in the html file itself, in addition to the highslide.config.js to manually override but it has not worked.
hs.registerOverlay({
html: '<div class="closebutton" onclick="return hs.close(this)" title="Close"></div>',
position: 'top right',
fade: 2 // fading the semi-transparent overlay looks bad in IE
});
Could somebody give me a helping hand?
////////////////////////////// updated
Thanks to Jeff B, I was able to accomplish the desired task using code that looks like this (although the example shown by Jeff B also works):
cursor: 'pointer',
point: {
events: {
click: function(event) {
hs.htmlExpand(null, {
pageOrigin: {
x: this.pageX,
y: this.pageY
},
headingText: this.ticker,
maincontentText: '<b>Detail:</b> ' + this.info,
width: 250
});
alert('function goes here');
hs.Expander.prototype.onBeforeClose = function(sender) {
alert('function goes here');
}
},
}
},
Why modify the button? Highslide provides an onBeforeClose prototype:
hs.Expander.prototype.onBeforeClose = function (sender) {
myotherfunction();
}
There is also an onAfterClose prototype if you want different timing.
onBeforeClose Documentation
Demo: http://jsfiddle.net/xjKFp/
I am trying to do a mouseover event for one picture where when you mouseover a div comes up and animates on the picture. When I do my mouseover though, it brings up both divs for separate pictures when I only want one at a time. Here is my code. The first part is the mouseover. Second is mouseout.
$('.portfolio img').mouseover(function(){
$(this).css('cursor', 'pointer');
$(this).parent().find('img:first').stop().animate({opacity:1}, 800, function() {
$("div.folio").animate({ height: '+=25px', top: '-=24px' }, 100, function() {
$("div.folio span").animate({ opacity: 1 }, 500);
});
});
});
$('.img_grayscale').mouseout(function(){
$(this).stop().animate({opacity:0}, 800, function() {
$("div.folio span").animate({ opacity: 0 }, 500, function() {
$("div.folio").animate({ height: '-=25px', top: '+=24px' }, 100);
$("div.folio").css('top', '-9px');
});
});
});
<div class="portfolio">
<h2>The Portfolio</h2>
<p class="slideTwo">Check out some of our recent projects.</p>
<ul>
<li><img src="portfolioOne.jpg"></img><div class="folio"><span>thesite.com</span></div></li>
<li><img src="portfolioOne.jpg"></img><div class="folio"><span>mysite.com</span></div></li>
</ul>
</div>
Using jQuery's $("div.folio") will return all divs with a class of "folio". Since you are seeing this animation on both images, rather than just the one you've moused-over, I'm assuming they both have the same class on the div they want to animate. In order to only animate one, you'll need to be more specific when selecting it with jQuery. Including $(this) on the path to the div to animate usually works, but I can't tell you the exact code without the corresponding HTML.
You need to cancel the bubble up event by returning "false" from your event handler.
$('.portfolio img').mouseover(function(){
// Your logic here...
return false;
});
There are a couple of concerns that I have about this which may or may not be problematic depending on what else is going on that you haven't shown.
You're doing $(this).parent().find('img:first') inside of a jQuery onmouseover function where $(this) should already be representing the img that you care about. Did you find that was necessary for some reason?
You could be more specific in your selector. Try doing $(".portfolio>ul>li>img")
img_grayscale is only mentioned once in your markup in your question so I'm not sure how that class gets applied but I'm assuming it does.
You could just add the class portfolio (or some unique identifier) to your images directly and probably have an easier time figuring out exactly why it isn't working as you expect. Then your mouseover selector could just be $(".specialClass")
You should definitely try posting a jsfiddle.net; you could borrow any two images off the web for testing.
Managed to figure this one out. I had to basically transverse the DOM through the following code. I referenced the image and then I went to the parent then to the next element in the DOM which was my div of div.folio. Then I went to the child of that object to fade it in. I did the same thing in reverse basically on the mouseout.
$('.portfolio img').mouseover(function(){
$(this).css('cursor', 'pointer');
$(this).parent().find('img:first').stop().animate({opacity:1}, 800, function() {
$(this).parent().next().animate({ height: '+=25px' }, 100, function() {
$(this).children().animate({ opacity: 1 }, 100);
});
});
});
$('.img_grayscale').mouseout(function(){
$(this).stop().animate({opacity:0}, 800, function() {
$(this).parent().next().children().animate({ opacity: 0 }, 100, function() {
$(this).parent().animate({height: '-=25px' }, 100);
});
});
});
I saw this technique at the bottom of a web page where the TAB stays in place at the bottom of the page and can be opened and closed to display more info. I assume it can be rotated to display a different special for different days. Can you point me to anything like it or explain the technique ? thanks. Here is a sample: http://www.tmdhosting.com/ look at the bottom of the page .
position: fixed is how you manage to keep something at the bottom or top of the page, regardless of scrolling.
This is easily discoverable using firebug's (http://getfirebug.com/) inspect element feature
You can check out my version of this at uxspoke.com
I wrote a jQuery plugin to do it, and calling it is straightforward:
$('#about').pulloutPanel({open:true}).
click(function() { $(this).trigger('toggle'); }) });
I basically instrument the panel to support "open", "close" events, and the implement the appropriate animations around them. The only "hard" part is getting the height right. It also supports "toggle" so you can add a generic click handler to it to open or close it. Finally, it uses opened/closed classes to keep track of its current state. That's it!
The code's pretty coupled to the technologies on the page (Csster) and the design it is in, so I'm not sure it will work for you. You can either use Csster, or just put the CSS rules into your stylesheet and remove them from the code. The important Css attributes are the positioning and bottom.
Here it is:
$.fn.pulloutPanel = function(options) {
var settings = $.extend({}, {
attachTo: 'bottom',
css: {
left: 0,
minHeight: 390,
border: '1px 1px 1px 0 solid #666',
has: [roundedCorners('tr', 10),boxShadow([0,0], 10, phaseToColor('requirements').saturate(-30).darken(50))],
cursor: 'pointer'
}, options);
return $(this).each(function() {
var $this = $(this);
$this.addClass('pullout_panel');
$this.bind('open', function(event) {
$this.animate({bottom: 0}, 'slow', 'easeOutBounce', function() {
$this.removeClass('closed').addClass('opened');
$this.trigger('opened');
});
});
$this.bind('close', function(event) {
var height = $this.innerHeight();
$this.animate({bottom: -height + 50}, 'slow', 'easeOutBounce', function() {
$this.addClass('closed').removeClass('opened');
$this.trigger('closed');
});
});
$this.bind('toggle', function(event) {
$this.trigger($this.hasClass('opened') ? 'close' : 'open');
});
once(function() {
Csster.style({
'.pullout_panel': {
position: 'fixed',
bottom: 0,
has: [settings.css]
}
});
});
$this.trigger(settings.open ? 'open' : 'close');
});
};
This function adds an overlay with the following properties to the entire browser screen,
$('a.cell').click(function() {
$('<div id = "overlay" />').appendTo('body').fadeIn("slow");
});
#overlay
{
background-color: black;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: none;
z-index: 100;
opacity: 0.5;
}
And this function is supposed to remove it.
$('#overlay').click(function() {
$(this).fadeOut("slow").remove();
});
But it seems to do absolutely nothing and now my page is stuck with a black overly over it. What's wrong with the removal?
The problem is that when you're adding the click handler, there isn't any overlay, so you're adding the handler to an empty set of elements.
To fix this, use the live method to bind your handler to all elements that match #overlay, whenever they are created.
Also, fadeOut is not a blocking call, so it returns before the element finishes fading out. Therefore, you're calling remove right after the element starts fading out.
To fix this, use fadeOut's callback parameter to call remove after the animation finishes.
For example:
$('#overlay').live(function() {
$(this).fadeOut("slow", function() { $(this).remove(); });
});
Here you go. This should fix the problem and let the overlay fade out before removing it.
$('#overlay').live("click", function() {
$(this).fadeOut("slow", function() { $(this).remove() });
});
Remove should be in the callback to fadeout, like so:
$('#overlay').live('click', function() {
$(this).fadeOut("slow", function() {
$(this).remove();
});
});
Try:
$('#overlay').live('click', function() {
$(this).fadeOut("slow").remove();
});
My recommendation is to use the jquery.tools overlay plugin. Your overlay will have a trigger (usually a button or link), but you can load or clear it with a javascript command, e.g.:
js:
var config = { closeOnClick:true, mask:{opacity:0.7, color:'#333', loadSpeed:1} }
$("#myTrigger").overlay(config); // add overlay functionality
$("#myTrigger").data("overlay").load(); // make overlay appear
$("#myTrigger").data("overlay").close(); // make overlay disappear
html:
<div id="myOverlay" style="display:none;">Be sure to set width and height css.</div>
<button id="myTrigger" rel="#myOverlay">show overlay</button>