Is it possible to make the suggestions of autocomplete (jQueryUI) get out one iframe, having the same behaviour of "select" element? I make one example:
http://jsbin.com/ehidef/1
As a matter of fact, it can be done, though some styling will be mandatory. jQueryUI accepts an element to append the options to, and you can pass the parent window as that element. An example:
main window:
<html>
<head></head>
<body>
<iframe src="iframe.html"></iframe>
</body>
</html>
iframe.html
<html>
<head>
<!-- include jQuery and jQuery UI and the like -->
<script type="text/javascript">
jQuery(function($){
// This will take parent frame if in iframe, own body elsehow
var el=top.document.body
// Instructs jQuery UI to show things on that previous element
$('input').autocomplete({appendTo:el});
});
</script>
</head>
<body>
<input type="text"/>
</body>
</html>
The whole example is missing all things not relevant to explainig the point, so it's not functional. Addapt as needed and add some suggar.
As for the styling i was refering before, you will have to give elements a position and style, as 1) position relative to input position is irrelevant on parent window and 2) parent doesn't need to have jqueryui stylesheets loaded, although you can load them dinamically from inside the iframe with a similar technique.
IMPORTANT:
This will only work if both, parent and child are in the same domain [see: SOP]
UPDATE
After finishing doing this same thing, i came up with this solution for styling and position:
var files=[ // UI styles to be loaded on top frame
"css/ui-lightness/jquery-ui-1.10.3.custom.css",
"css/ui-lightness/custom.css"
]
// Create link tag and append to top frame head
for (var a in files) {
var style=$("<link/>", {
rel: "stylesheet",
type: "text/css",
href: files[a]
});
$(top.document).find('head').append(style);
}
// As it turns out i had many iframes, so this will get the right one
var parentIframe=$(el).find('iframe').filter(function(){
return window.frameElement==this
});
$('input').each(function(){ // Cicle inputs to use with ui autocomplete
// set position to left + input offset 2 is a fix for borders on input
var pos= "left+"+($(this).offset().left+2)+
// and to top + input position + height to have it on the bottom
" top+"+($(this).offset().top+$(this).outerHeight()+1);
// Autocomplete
$(this).autocomplete({
appendTo:top.document.body, // put it on top window's body
position:{
at: pos, // at calculated position
of:parentIframe // from parent iframe
}
})
});
Once again, there may be voids, so fill up with relevant code at will
Related
I have set up a slider with jquery ui. I want the handle of the slider to be hidden initially and only show up, after the user clicks on the slider. I managed to hide the handle by setting display to none in the ui-slider-handle class. However, I am not able to change it back later on.
Consider the following code snippet, based on https://api.jqueryui.com/slider/ example.
$(function() {
$("#slider").slider({
start: function() {
$(".ui-slider-handle", this).show();
}
});
var sw = $("#slider").slider("widget");
$(".ui-slider-handle", sw).hide();
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="slider"></div>
Yes, you can hide the handle with CSS, to make it appear again would just mean over riding the CSS with an element style:
$(".ui-slider-handle").css("display", "block");
The example above is a bit more specific, yet essentially does the same thing. Once the Slider is initialized, you can call the widget method to access the various elements. We can use .hide() on the handle. When the User clicks on the Slider, this triggers the start event and we can .show() the handle at that time.
If you have multiple sliders, the ui-slider-handle class might be too ambiguous, so using the selector context will help.
Internally, selector context is implemented with the .find() method, so $( "span", this ) is equivalent to $( this ).find( "span" ).
See More:
https://api.jqueryui.com/slider/#method-widget
https://api.jqueryui.com/slider/#event-start
https://api.jquery.com/show/
https://api.jquery.com/hide/
https://api.jquery.com/jquery/#selector-context
I have a slideshow plugin called flexslider which is only displayed after the page has fully loaded and all images have been downloaded.
I also have an anchor tag on this page which is being invoked before the page has fully loaded.
This is causing the anchor tag to be in the wrong place as the page height has changed to accommodate the slideshow.
You can see what I mean here: http://ypc.org.au/ministries/form#transform2015
I've duplicated the page and removed the slideshow and it seems to work but I need it working with the slideshow:
http://ypc.org.au/ministries/form2#transform2015
Can someone suggest how I could make the anchor tag load only after the page has fully loaded? Or is there something simple I am missing?
Thanks!
Edit:
I think this might be how flexslider is loading the page:
<script type="text/javascript">
$(function(){
SyntaxHighlighter.all();
});
$(window).load(function(){
$('.flexslider').flexslider({
animation: "slide",
start: function(slider){
$('body').removeClass('loading');
}
});
});
</script>
This is probably your solution. Use this jQuery code.
<script type="text/javascript">
$(window).load(function() {
$(".your-anchor-tag").fadeOut();
});
</script>
I had the same problem, because i was using a slideshow, and because of other responsive elements so i can't determine the height of the images for example.
You can use a JQuery script, this can postpone the anchor link after the page is loaded, i added an offset of 20 px also (if you have a sticky menu bar you can make this space bigger).
$(document).ready(function() {
if(window.location.hash) {
$('html, body').animate({
scrollTop: $(window.location.hash).offset().top - 20
}, 500);
}
});
<!-- my-poly -->
<template>
<content select=".useBtn">
<button id="defaultBtn">
<content select=".useBtnIcon">
Button
</content>
</button>
</content>
</template>
So if my Element gets used, the User can input a Button which will be shown instead of the defaultBtn. But if no Button is given, the defaultBtn with the Button Text will be shown. But the user also should have the Option to use the defaultBtn and to input a text or icon which will be shown in the Button.
If I use a <div class="useBtn"></div> it will be used as the Button. But <div class="useBtnIcon"> BtnText</div> does not seem to work. Is there a way to make this work?
According to the spec its not going to work.
http://www.w3.org/TR/shadow-dom/#content-insertion-points
The content element that satisfies all of the following conditions represents a content insertion point:
The root node of the content element is a shadow root
There is no other content element in the ancestors of the content element
There is no shadow element in the ancestors of the content element
With this in mind, i guess, you cant make this thing work with nestetd content elements.
This one will work. Custom Icon wins if both are applied
<polymer-element name="the-button">
<template>
<content id="contentButton" select=".useBtn">
<button id="PREFIXEDdefaultBtn">
Default Button
</button>
</content>
<button id="defaultBtnWithCustomIcon">
<!--be sure that this content element doesnt contain a default set -->
<content id="contentIcon" select=".useBtnIcon"></content>
</button>
</template>
<script>
Polymer('the-button', {
domReady: function () {
var customIcon = this.$.contentIcon;
var disNodes = customIcon.getDistributedNodes();
//Test if the content element contains distributed nodes.
if (disNodes.length !== 0) {
this.$.contentButton.remove();
} else {
// the button is customized, remove the icon
this.$.defaultBtnWithCustomIcon.remove();
}
}
});
</script>
</polymer-element>
I'm pretty sure that your inner <content> element is purged when the outer <content> element selects its content.
Can you provide a jsfiddle or plnkr or anything for this? Polymer imports so many things, it's hard to trouble-shoot an issue without building our own project ourselves.
Without having the source to trouble-shoot this, it sounds like you might need to add the attributes to allow users to change preferences within your element in the <polymer-element> tag:
<polymer-element name="my-element" attributes="defaultBtn inputBtn">
See here: https://www.polymer-project.org/docs/polymer/polymer.html#declarative-event-mapping
That should allow users to configure your custom element. Once again, without having the code to tinker with, not sure if this is going to work for your situation?
I'm using jQueryUI Tabs inside a jQueryUI Dialog box. The content in each of the tab panels can be quite large -- for example there can be a table with hundreds of rows inside each individual tab panel. So scrollbars are required to navigate the content.
By default, the dialog panel displays its own scrollbar -- which is not exactly what I want. This scrollbar causes the navigation tabs themselves to move up and out of view. What I'd prefer is for each tab panel to display its own scrollbar if necessary but to leave the navigation tabs visible. I've tried setting "overflow:hidden" for the dialog panel, and then "overflow:auto" for the individual tab panels (see below). But then the tab panels are not getting scrollbars even when the content requires it.
Below is a (reduced) test case that shows the problem -- including my attempt to use overflow styles to solve the problem. Replace "Big content..." with something that causes scrollbars to be required and you'll see it.
Hope that's clear enough. Any ideas on how to solve this problem? Many thanks...
<html>
<head>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#dialog").dialog({height:300});
$("#tabs").tabs();
});
</script>
</head>
<body>
<div id="dialog" style="overflow:hidden;">
<div id="tabs">
<ul>
<li>tab-1</li>
<li>tab-2</li>
</ul>
<div id="tab-1" style="overflow:auto;">Big content...</div>
<div id="tab-2" style="overflow:auto;">Big content...</div>
</div>
</div>
</body>
</html>
You could limit the height of each div which contains your 'content' ie:
height:100px;
overflow:auto;
Demo: http://jsfiddle.net/AeXNP/
Which makes everything very simple.
Edit: The harder part comes when (as you requested below) that the content resizes based on the user resizing the dialog. In involves a lot more css... To use overflow in your case, you require a height of the div. As the height is changing all the time, you don't know what height it will be. Therefore you need to manually set a margins and padding so you can set the height to 'auto'. So the css for the self-expanding tab contents is:
.fixedSizedTab {
overflow:auto;
position:absolute;
height:auto;
bottom:0;
top:0;
left:0;
right:0;
margin-top:50px;
margin-bottom:10px;
margin-right:0px;
margin-left:0px;
}
Demo: http://jsfiddle.net/AeXNP/2/
What a mouthful.
Basically I have a parent <div> and inside that an <iframe>. I need an element inside the iframe to be the handle to drag the parent div. Is this even possible?
I have tried:
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle'));
$(node).draggable("option","handle",$('iframe',node).contents().find('#handle')[0]);
It is targeting the right DOM element but it just won't drag. It might be possible to overlay a hidden div ontop of the iframe but I have found the iframe takes the event over the div when position is absolute. Strange.
try this
$('#Div').draggable({ iframeFix: true });
this should work
I decided to take a stab at this and boy, it's a lot of work with little progress using an internal iframe node as a handle. Anyway, here are two solutions, the first one doesn't work really well, but if you can get it to work, it may be more desirable.
main.html (plagiarized from the demo)
<div id="draggable" class="ui-widget-content" style="position:relative;">
<p class="ui-widget-header">I can be dragged only by this handle</p>
<iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
</div>
inner-handle.html
<html>
<head>
<script type="text/javascript" src="../../jquery-1.4.2.js"></script>
</head>
<body>
<div id="innerHandle">handle</div>
</body>
</html>
JavaScript
$(function () {
var moveEvent;
$(document).mousemove(function (e) {
moveEvent = e;
});
$("#draggable").draggable();
$('iframe', '#draggable').load(function () {
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
$('#draggable').draggable().data('draggable')._mouseDown(moveEvent);
return false;
});
});
});
It took me a while to find something that "worked." The problem here was that since the mousedown event occurred on an element inside the iframe, the mouse event is relative to the iframe, not the main document. The workaround is to have a move event on the document and grab the mouse position from there. The problem, once again, is that if the mouse is inside of the iframe, it is "not" moving according to the parent document. This means that the drag event only happens when the mouse reaches the edge of the iframe into the parent document.
A workaround for this might be to manually generate events with the calculated position of the iframe relative to its mouse movement. So when your mouse moves within the iframe, calculate its movement using the coordinate of the iframe to the parent document. This means that you need to use the event from the mousedown and not the mousemove,
$('iframe', '#draggable')[0].contentWindow.$('#innerHandle').mousedown(function (e) {
// do something with e
$('#draggable').draggable().data('draggable')._mouseDown(e);
return false;
});
The second solution is the way you have mentioned, have an absolute positioned div over the iframe itself. I have no trouble in getting the div to be on top of the iframe, that is,
<div id="draggable" class="ui-widget-content" style="position:relative;">
<p class="ui-widget-header">I can be dragged only by this handle</p>
<iframe name="iframe1" src="inner-handle.html" height=50 width=80></iframe>
<div style="position: absolute; height: 30px; width: 30px; background-color: black; z-index: 1000;"></div>
</div>
The problem with your div being behind the iframe might be because the z-index is off. If you declare your div before the iframe and you didn't specify the z-index, then the iframe will be on top.
Whichever way you choose, good luck!
what happens when you do this (with firebug activated):
var frameContent = $('iframe',node).contents()
var handle = frameContent.find('#handle');
console.debug(frameContent, handle)
Does handle contain a list of elements? And if so, look carefully at the Document object which is frameContent - is the URL "about:blank"? It's just a hunch, but if you get these outputs, it's probably executing the jQuery selector before the frame content has loaded (i.e., before the #handle element exists).
In which case, you can add an event to the IFRAME'd document, and communicate with the parent frame via window.parent.