function being called with ID, change to onclick? - javascript

I have an overlay script that pops up when a link like:
<a id="b1" href="page.html">link</a>
is used. The problem is that I need multiple links but can't use the same ID.
Here is the code:
$(function(){
$('#b1').frameWarp();
});
I have tried replace #b1 with .b1 and a.b1 and using class instead of ID. This works fine on the first link but any subsequent links clicked cause the first page clicked to open again. I think there is a conflict with classes already being used in the script for the overlay.
Is there a way I can use onclick in to get this to work the same way?
The script is from a plugin but here is the rest of it:
(function($){
// Private varialble deffinitions
var body = $('body'),
win = $(window),
popup, popupBG;
var frameCache = {};
var frameCacheDiv = $('<div class="frameCacheDiv">').appendTo('body');
var currentIframe;
// The main plugin code
$.fn.frameWarp = function(settings){
// Supplying default settings
settings = $.extend({
cache: false,
url: '',
width:600,
height:500,
closeOnBackgroundClick: true,
onMessage:function(){},
onShow:function(){}
}, settings);
this.on('click',function(e){
e.preventDefault();
var elem = $(this),
offset = elem.offset();
// The center of the button
var buttonCenter = {
x: offset.left - win.scrollLeft() + elem.outerWidth()/2,
y: offset.top - win.scrollTop() + elem.outerHeight()/2
};
// The center of the window
var windowCenter = {
x: win.width()/2,
y: win.height()/2
};
// If no URL is specified, use the href attribute.
// This is useful for progressively enhancing links.
if(!settings.url && elem.attr('href')){
settings.url = elem.attr('href');
}
// The dark background
popupBG = $('<div>',{'class':'popupBG'}).appendTo(body);
popupBG.click(function(){
if(settings.closeOnBackgroundClick){
hide();
}
}).animate({ // jQuery++ CSS3 animation
'opacity':1
},400);
// The popup
popup = $('<div>').addClass('popup').css({
width : 0,
height : 0,
top : buttonCenter.y,
left : buttonCenter.x - 35
});
// Append it to the page, and trigger a CSS3 animation
popup.appendTo(body).animate({
'width' : settings.width,
'top' : windowCenter.y - settings.height/2,
'left' : windowCenter.x - settings.width/2,
'border-top-width' : settings.height,
'border-right-width' : 0,
'border-left-width' : 0
},200,function(){
popup.addClass('loading').css({
'width': settings.width,
'height': settings.height
});
var iframe;
// If this iframe already exists in the cache
if(settings.cache && settings.url in frameCache){
iframe = frameCache[settings.url].show();
}
else{
iframe = $('<iframe>',{
'src' : settings.url,
'css' : {
'width' : settings.width,
'height' : settings.height,
}
});
// If the cache is enabled, add the frame to it
if(settings.cache){
frameCache[settings.url] = iframe;
iframe.data('cached',true);
settings.onShow();
}
else{
// remove non-cached iframes
frameCacheDiv.find('iframe').each(function(){
var f = $(this);
if(!f.data('cached')){
f.remove();
}
});
}
iframe.ready(function(){
frameCacheDiv.append(iframe);
setUpAPI(iframe, settings);
settings.onShow();
});
}
currentIframe = iframe;
});
});
return this;
};
// Helper Functions
function hide(){
if(currentIframe){
currentIframe.hide();
currentIframe = null;
}
popupBG.remove();
popup.remove();
}
function setUpAPI(iframe, settings){
if(sameOrigin(settings.url)){
// Exposing a minimal API to the iframe
iframe[0].contentWindow.frameWarp = {
hide: hide,
sendMessage:function(param){
return settings.onMessage(param);
}
};
}
}
function sameOrigin(url){
// Compare whether the url belongs to the
// local site or is remote
return (getOrigin(url) == getOrigin(location.href));
}
function getOrigin(url){
// Using an anchor element to
// parse the URL
var a = document.createElement('a');
a.href = url;
return a.protocol+'//'+a.hostname;
}
})(jQuery);

Try this:
link1
link2
link3
Have not tried it but should work

Related

Problems with iframe when used more than once on the page

I'm creating a quickview functionality, where you can see the contents of each item in a product listing directly in a modal that will open.
In the modal there is a frame that is generated dynamically with javascript, and I place the url of my controller that renders the modal content (url like this http://localhost/quickview/product/view/id/18564/).
When the modal is closed, I delete the modal content, and when the user wants to see the content of another product on the same page, I re-generate an iframe element with javascript and display.
The problem is that after the first modal view, the iframe loads and displays the content again but the javascript that runs in the iframe (we have an image gallery in the product content) does not work. Soon after the second attempt in front of the gallery and all other behaviors with javascript do not work, although modal, iframe and content coming from the controller are correct.
I already tried to reload the same iframe (without destroying it) and display it again, I tried to create the iframe with id different to each modal view, but I could not solve it once. Below the javascript I use to generate the modal and the iframe. The controller I do not believe is relevant (whenever I open the url of the content in a new tab everything works perfectly, as well as being independent of the product every time I open the modal first, everything loads correctly in the modal).
var ProductInfo = Class.create();
ProductInfo.prototype = {
settings: {
'loadingMessage': 'aguarde ...',
'viewport': document.viewport.getDimensions()
},
idframe: 'quick-frame',
initialize: function(selector, x_image, settings) {
Object.extend(this.settings, settings);
this.createWindow();
var that = this;
$$(selector).each(function(el, index){
el.observe('click', that.loadInfo.bind(that));
})
},
createLoader: function() {
var loader = new Element('div', {id: 'pleaseWaitDialog'});
var imgLoader = new Element('img', {src: '/js/inovarti/ajax-loader.gif', alt: this.settings.loadingMessage, id: 'loading-quickview-img'});
var contentLoader = new Element('p', {class: 'loader'});
contentLoader.setStyle({
'display': 'block',
'margin-top': (this.settings.viewport.height/2 - contentLoader.getHeight()/2)+'px',
'text-align': 'center'
});
contentLoader.appendChild(imgLoader);
loader.appendChild(contentLoader);
document.body.appendChild(loader);
$('pleaseWaitDialog').setStyle({
'position': 'fixed',
'top': 0,
'left': 0,
'width': '100%',
'height': '100%',
'display': 'block',
'opacity': '.8',
'background': '#FFFFFF',
'z-index': '99999'
});
},
destroyLoader: function(full) {
if(full) {
$('pleaseWaitDialog').remove();
}
else {
if($('loading-quickview-img') != null) {
$('loading-quickview-img').remove();
}
$('pleaseWaitDialog').setStyle({'background-color': '#000000'});
}
},
showButton: function(e) {
el = this;
while (el.tagName != 'P') {
el = el.up();
}
$(el).getElementsBySelector('.quickview-ajax')[0].setStyle({
display: 'block'
})
},
hideButton: function(e) {
el = this;
while (el.tagName != 'P') {
el = el.up();
}
$(el).getElementsBySelector('.quickview-ajax')[0].setStyle({
display: 'none'
})
},
createWindow: function() {
var qWindow = new Element('div', {id: 'quick-window'});
qWindow.innerHTML = '<div id="quickview-header" style="width: 100%; text-align: right;"><i class="glyphicon glyphicon-remove"></i></div><div class="quick-view-content"></div>';
document.body.appendChild(qWindow);
$('quickview-close').setStyle({
'padding-right': "20px",
'padding-left': "20px"
});
$('quickview-close').observe('click', this.hideWindow.bind(this));
},
showWindow: function() {
var screenWidth, offsetTopModal;
if(document.body.clientWidth > 1400) {
screenWidth = 1400;
offsetTopModal = 100;
}
else {
if(document.body.clientWidth < 768) {
screenWidth = document.body.clientWidth;
offsetTopModal = 0;
}
else {
screenWidth = document.body.clientWidth * 0.8;
offsetTopModal = 100;
}
}
var windowWidth = screenWidth;
$('quick-window').setStyle({
'top': document.viewport.getScrollOffsets().top + offsetTopModal + 'px',
'left': document.body.clientWidth/2 - windowWidth/2 + 'px',
'display': 'block',
'position': 'absolute',
'width': windowWidth + 'px',
'background': '#FFFFFF',
'padding': '20px 0px',
'margin-bottom': '20px',
'border': '1px solid #F0F0F0',
'z-index': '999999',
'border-radius': '4px'
});
$('pleaseWaitDialog').observe('click', this.hideWindow.bind(this));
this.resizeIframe($(this.idframe));
},
setContent: function(srcUrl) {
var options = {
id: this.idframe,
frameborder: "0",
scrolling: "no",
src: srcUrl,
hspace: "0",
name: this.idframe+(new Date().getTime()),
width: "100%"
};
var frame = new Element('iframe', options);
$$('.quick-view-content')[0].insert(frame);
},
clearContent: function() {
$$('.quick-view-content')[0].replace('<div class="quick-view-content"></div>');
},
hideWindow: function() {
this.clearContent();
this.destroyLoader(true);
$('quick-window').hide();
},
loadInfo: function(e) {
e.stop();
var that = this;
this.createLoader();
this.clearContent();
this.setContent(e.element().href);
Event.observe($(this.idframe), 'load', function() {
window.quickview.completeInfo();
setTimeout(function () {
window.quickview.resizeIframe($(this.idframe));
},500);
});
},
completeInfo: function () {
this.destroyLoader(false);
this.showWindow();
},
resizeIframe: function(obj) {
if(obj) {
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
obj.style.width = "100%";
}
}
}
Event.observe(window, 'load', function() {
window.quickview = new ProductInfo('.quickview-ajax', '.product-image', {
});
});
I believe it is not relevant, but the application is Magento 1.9.3.9, so I'm using prototype as js framework (native from Magento).
A curious fact, if I update the frame through the browser using the right button and requesting the "Refresh Frame" with mouse, the iframe is updated correctly and the content javascript loads correctly.
UPDATE:
By performing some tests, I noticed that the first time the iframe is loaded, the width of the iframe is detected in js inside iframe. But in the other times that it is created and inserted, the width is detected as zero. Below the tests:
//First open
console.log(document.documentElement.clientWidth);
//output: 1356
//Second open
console.log(document.documentElement.clientWidth);
//output: 0
OwlCarousel2 do a throw (more details in https://github.com/OwlCarousel2/OwlCarousel2/issues/1704), and I think de JS stop with the exception.
Owl.prototype.viewport = function() {
var width;
if (this.options.responsiveBaseElement !== window) {
width = $(this.options.responsiveBaseElement).width();
} else if (window.innerWidth) {
width = window.innerWidth;
} else if (document.documentElement && document.documentElement.clientWidth) {
width = document.documentElement.clientWidth;
} else {
throw 'Can not detect viewport width.';
}
return width;
};
Even though I change OwlCarousel2 (the latest version doesn't has a throw), I believe that the fact that the width is being detected incorrectly will generate several other problems.
I also updated the iframe by always creating it 100% wide, but the problem still persists.
It is a jQuery cache issue. You should send headers from your server in order to not cache the iframe in the client:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
You can also force a iframe refresh by using:
iframe.contentWindow.location.reload(true);
Update
var nameOrIndex = 'nameOrIndex'; // i.e. 'my_iframe' or '0'
var iFrame = window.frames[nameOrIndex];
if (iFrame) {
var document = iFrame.contentDocument ? iFrame.contentDocument : iFrame.contentWindow ? iFrame.contentWindow.document : iFrame.document;
if (document && document.location) {
document.location.reload(true); // 1 (sandboxing, same domain origin policy)
document.location.href = document.location.href; // 2 (cross domain, might detect size changes)
}
if (iFrame.src) {
window.frames[nameOrIndex].src = iFrame.src; // 3 (cross domain, might detect size changes)
}
$(iFrame).replaceWith($(iFrame).clone()); // 4 (cross domain, might detect size changes)
}
However, regarding your size problem look at this SO question

'Close' button does not work in javascript

In the mobile version on my form appears 'Close' button.
Unfortunately, it does not work. I see a normal button, but when I click there is no reaction. In the javascript I load the file form-with-button.html to render form content in my all .html files.
<div id="form-with-button">
</div>
and use javascript to show and close.
//Onload show header and footer content
$("#header").load('header.html', function(){
$('#nav').affix({
offset: {top: $('#header').height()-$('#nav').height()}
});
});
$("#footer").load('footer.html');
$("#contact").load('footer-contact.html');
$("#form-with-button").load('form-with-button.html');
// Sticky Buttons Show Hide
$("#fix-quote, #fix-contact").on("click", function() {
var body = $("body");
var openPos= ["",""];
var id = $(this).attr("id");
var content = $("#"+id+"-content");
var property = (content.attr("class").toString().indexOf("left") > -1)? "left": "right";
if (!body.hasClass("bd_"+id)) {
openPos= [0,380]
var ele = $(this);
body.addClass("bd_"+id)
setTimeout(function(){
body.on("click.fix",function(ev) {
if($(ev.target).closest(".fixed-container").length == 0){
$(ele).click()
}
});
},10);
} else {
body.removeClass("bd_"+id).off("click.fix");
}
content.css("top","").show().css(property, openPos[0]);
$(this).css(property, openPos[1]);
});
// Mobile Requests Showhide
$("#fix-quote-mob, #fix-contact-mob").on("click", function() {
var id = $(this).attr("id").slice(0,-4);
var content = $("#"+id+"-content");
content.show()
setTimeout(function(){
content.css("top",0)
},10)
});
$(".fix-contact-close").on("click", function() {
var content = $(this).closest(".fixed-container");
content.css("top","").delay(400).hide(0);
});
Please help, why my button does not work?
You are trying to add a handler to an element created in a dynamic way, so you need to refactor your code in order to make it work:
$(document).on("click", ".fix-contact-close", function() {
var content = $(this).closest(".fixed-container");
content.css("top","").delay(400).hide(0);
});

Titanium, waiting for files to be fetched and downloaded remotely before displaying window

Scienario:
I have a window, and I am fetching data remotely over a http protocol. What is the best way in titanium to prevent the window displaying the data prematurely.
In many mobile apps, they get around this problem by having a load indicator , everytime you open a window, how can you do this in titanium?
$.window.addEventListener('load',function(){
..
//some text
..
});
I have tried this, but I am not sure what to do next, as my async methods are fired outside of it. So not sure if this will have any affect.
thanks
Translating this from jquery:
$.ajaxSetup({
beforeSend: function() {
// show loading overlay gif
$("#Loading").show();
},
complete: function() {
// hide loading overlay gif
$("#Loading").hide();
}
});
$.ajax({
type: "GET",
url: url,
data: param = "",
contentType: "application/json; charset=utf-8",
success: doSomething,
error: errorFunction
});
};
Ajax setup means every time I fire an Ajax request, an loading overlay will appear on the screen until the response is received. How can I achieve the same thing in titanium?
Update:
Is this a good way to do it?
Albums.JS
function getAlbumCovers() {
//first check to see if profile pics already exist in user model
//create a collection
var usersCollection = Alloy.Collections.user;
facebookModule.requestWithGraphPath('me/albums', {
fields : 'id,name,cover_photo,count,created_time'
}, 'GET', function(graphResp) {
//show view indicator before data is fetched
$.view_indicator.visible = true;
if (graphResp.success) {
if (graphResp.result) {
var rows = [];
var data = JSON.parse(graphResp.result).data;
for (x in data) {
Ti.API.debug(JSON.stringify(data[x]));
if (data[x].name == "Profile Pictures") {
var row = Titanium.UI.createTableViewRow({
width : '100%',
height : 'auto'
});
var image = Titanium.UI.createImageView({
image : "https://graph.facebook.com/" + (data[x].cover_photo || 0) + "/picture?access_token=" + Ti.Facebook.accessToken,
top : 0,
left : 0,
width : 100,
height : 100
});
var title = Titanium.UI.createLabel({
text : String.format("%s (%d)", data[x].name, data[x].count),
top : 0,
left : 110,
width : 'auto',
height : 'auto'
});
row.add(image);
row.add(title);
rows.push(row);
} else {
break;
}
}
//set table rows
$.tableview.setData(rows);
//end
}
$.view_indicator.visible = false;
} else {
if (e.error) {
alert(e.error);
} else {
alert("Unkown result");
}
}
});
}
Albums.XML
<Alloy>
<Window id="win" backgroundColor="white">
<LeftNavButton>
<Button id="lbtn" onClick="rightButtonClicked" />
</LeftNavButton>
<RightNavButton>
<Button id="btnRight" onClick="rightButtonClicked" />
</RightNavButton>
<View id = "view_indicator">
<ActivityIndicator id="ind" />
</View>
<TableView id="tableview"></TableView>
</Window>
</Alloy>
App.tss
//overlay
//loading overlay to cover full screen
"#view_indicator": {
backgroundColor : '#000',
opacity : 0.6,
width : '100%',
height : '100%',
borderRadius : 5,
zIndex: 20,
visible : false
},
"#ind": {
style : Ti.UI.iPhone.ActivityIndicatorStyle.BIG,
visible : true
},
In this instance I have made a call to Facebook api, and placed $.view_indicator.visible = true; just before if (graphResp.success) { function. The loading overlay is removed once if (graphResp.success) { is hit.
The idea is, the end user has to wait for the table to be populated before seeing the tableview.
I am not sure if this is the correct way of doing this. Could someone confirm, cheers.
You can achieve this effect by calling window.open() at the end of onload callback in `HTTPClient.
var window = Ti.UI.createWindow();
var http = Ti.Network.createHTTPClient({
onload: function(e) {
var response = this.responseText;
/* Add views to window based on response */
window.open();
}
});
http.open('GET', url);
httpCallbackDecorator(http);
http.send();
function httpCallbackDecorator(http) {
var onloadCallback = http.onload;
var onerrorCallback = http.onerror;
http.onload = function(event) {
onloadCallback.call(this, event);
hideLoadingIndicator();
}
http.onerror = function(event) {
onerrorCallback.call(this.event);
hideLoadingIndicator();
}
}

Modify collapse.js to get addtional data from xml when expanding fieldset in Drupal 7?

In drupal i have generated a list where each item is a fieldset with collapsible, that can contain extra information.
Because of the rather large list i want to avoid loading the extra information until a user clicks on the fieldset.
Best case scenario:
User clicks on collapsed fieldset.
Fieldset loads extra information.
Fieldset uncollapses.
I've copied and loaded the copy of collapse.js into my form, but I'm very new to js and jQuery, so I'm a little lost. If someone can show me how to call a function the first time the fieldset is expanded, I'm sure i can figure out the rest.
I've included the code from collapse.js:
(function ($) {
//Toggle the visibility of a fieldset using smooth animations.
Drupal.toggleFieldset = function (fieldset) {
var $fieldset = $(fieldset);
if ($fieldset.is('.collapsed')) {
var $content = $('> .fieldset-wrapper', fieldset).hide();
$fieldset
.removeClass('collapsed')
.trigger({ type: 'collapsed', value: false })
.find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
$content.slideDown({
duration: 'fast',
easing: 'linear',
complete: function () {
Drupal.collapseScrollIntoView(fieldset);
fieldset.animating = false;
},
step: function () {
// Scroll the fieldset into view.
Drupal.collapseScrollIntoView(fieldset);
}
});
}
else {
$fieldset.trigger({ type: 'collapsed', value: true });
$('> .fieldset-wrapper', fieldset).slideUp('fast', function () {
$fieldset
.addClass('collapsed')
.find('> legend span.fieldset-legend-prefix').html(Drupal.t('Show'));
fieldset.animating = false;
});
}
};
//Scroll a given fieldset into view as much as possible.
Drupal.collapseScrollIntoView = function (node) {
var h = document.documentElement.clientHeight || document.body.clientHeight || 0;
var offset = document.documentElement.scrollTop || document.body.scrollTop || 0;
var posY = $(node).offset().top;
var fudge = 55;
if (posY + node.offsetHeight + fudge > h + offset) {
if (node.offsetHeight > h) {
window.scrollTo(0, posY);
}
else {
window.scrollTo(0, posY + node.offsetHeight - h + fudge);
}
}
};
Drupal.behaviors.collapse = {
attach: function (context, settings) {
$('fieldset.collapsible', context).once('collapse', function () {
var $fieldset = $(this);
// Expand fieldset if there are errors inside, or if it contains an
// element that is targeted by the uri fragment identifier.
var anchor = location.hash && location.hash != '#' ? ', ' + location.hash : '';
if ($('.error' + anchor, $fieldset).length) {
$fieldset.removeClass('collapsed');
}
var summary = $('<span class="summary"></span>');
$fieldset.
bind('summaryUpdated', function () {
var text = $.trim($fieldset.drupalGetSummary());
summary.html(text ? ' (' + text + ')' : '');
})
.trigger('summaryUpdated');
// Turn the legend into a clickable link, but retain span.fieldset-legend
// for CSS positioning.
var $legend = $('> legend .fieldset-legend', this);
$('<span class="fieldset-legend-prefix element-invisible"></span>')
.append($fieldset.hasClass('collapsed') ? Drupal.t('Show') : Drupal.t('Hide'))
.prependTo($legend)
.after(' ');
// .wrapInner() does not retain bound events.
var $link = $('<a class="fieldset-title" href="#"></a>')
.prepend($legend.contents())
.appendTo($legend)
.click(function () {
var fieldset = $fieldset.get(0);
// Don't animate multiple times.
if (!fieldset.animating) {
fieldset.animating = true;
Drupal.toggleFieldset(fieldset);
}
return false;
});
$legend.append(summary);
});
}
};
})(jQuery);
It looks to me like you'd have to override the whole Drupal.toggleFieldset function (just like when you are overriding a Drupal theme function.
You could perhaps add a class to the fieldset in FormAPI then catch it in the complete function of the $content.slideDown params and fire a custom function of yours, to add a 'loading' graphic and make your ajax request.
I'm assuming from your question that you are familiar enough with FormAPI/jQuery.ajax() to have a go. But let me know if not and i'll include some snippets
EDIT
Here is some example code, it'd take a quite a while to setup a test environment for this, so it'just a pointer (cant create a JS fiddle for this ;))
You might add your fieldset like this in PHP
$form['my_fieldset'] = array(
'#type' = 'fieldset',
'#title' = t('My fieldset'),
'#collapsible' = true,
'#collapsed' = true,
'#attributes' => array(
'class' => array('ajax-fieldset'),
'rel' => 'callback/url/path' // random attribute to store the link to a menu path that will return your HTML
)
);
$form['my_fieldset'] = array(
'#markup' => '<div class="response">loading...</div>'
);
You'll also obviously have setup a menu hook returning your themed data # callback/url/path. IMO it's better to return JSON data and theme them in with JS templating, but the Drupal way (for the moment at least) seems to be to render HTML in the menu hook callback function.
Then here is the JS. I've only included the altered complete function, rather than reproduce what you pasted. Add the complete function in to a copy of the code the re-specify the core Drupal function in your own JS file
$content.slideDown({
complete: function () {
Drupal.collapseScrollIntoView(fieldset);
fieldset.animating = false;
if($fieldset.hasClass('ajax-fieldset')) {
$.get(
Drupal.settings.basePath + $fielset.attr('rel'),
function(data) {
$fieldset.find('.response').html(data);
}
)
}
}
});
Or, rather than messing around with the collapsible function. just create your own fieldset without the collapsible/collapsed classes and implement from scratch yourself
....so.. something like that :)

Open Select using Javascript/jQuery?

Is there a way to open a select box using Javascript (and jQuery)?
<select style="width:150px;">
<option value="1">1</option>
<option value="2">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc arcu nunc, rhoncus ac dignissim at, rhoncus ac tellus.</option>
<option value="3">3</option>
</select>
I have to open my select, cause of IE bug. All versions of IE (6,7,8) cut my options.
As far as I know, there is no CSS bugfix for this.
At the moment I try to do the following:
var original_width = 0;
var selected_val = false;
if (jQuery.browser.msie) {
$('select').click(function(){
if (selected_val == false){
if(original_width == 0)
original_width = $(this).width();
$(this).css({
'position' : 'absolute',
'width' : 'auto'
});
}else{
$(this).css({
'position' : 'relative',
'width' : original_width
});
selected_val = false;
}
});
$('select').blur(function(){
$(this).css({
'position' : 'relative',
'width' : original_width
});
});
$('select').blur(function(){
$(this).css({
'position' : 'relative',
'width' : original_width
});
});
$('select').change(function(){
$(this).css({
'position' : 'relative',
'width' : original_width
});
});
$('select option').click(function(){
$(this).css({
'position' : 'relative',
'width' : original_width
});
selected_val = true;
});
}
But clicking on my select the first time will change the width of the select but I have to click again to open it.
I know this is pretty old and answered, but this worked for me in Safari and iOS UIWebView - I have it hidden, but want it to show and open when a different button is clicked.
$('#select-id').show().focus().click();
Try this:
var myDropDown=$("#myDropDown");
var length = $('#myDropDown> option').length;
//open dropdown
myDropDown.attr('size',length);
and this to close:
//close dropdown
myDropDown.attr('size',0);
Instead of using click, you could use the mousedown handler to capture the mousedown event.
mousedown fires before click, so you could call stopPropogation to break the event queue.
Try this:
dropDown = function (elementId) {
var dropdown = document.getElementById(elementId);
try {
showDropdown(dropdown);
} catch(e) {
}
return false;
};
showDropdown = function (element) {
var event;
event = document.createEvent('MouseEvents');
event.initMouseEvent('mousedown', true, true, window);
element.dispatchEvent(event);
};
Then call the function:
dropDown('elementId');
NO jQuery solution.
<SCRIPT>
function toggleDropdown(element){
if(element.size == 0) {
element.size = element.length;
element.focus();
}
else element.size = 0;
}
</SCRIPT>
Found this here.
First of all, I feel the pain of this limitation in IE - bleh!
Just thought I'd also share this as it seems to be working for me. I've taken almost the same approach, but on a per select element. In my case I know which lists could have long data.
Instead of making the select elements absolute, I've kept them inline and wrap them in a DIV with a hidden overflow as appearance needed to be consistent, also it only applies this 'hack' if it is IE and the expanded width is greater than the current width.
To use this for all select boxes you could use something like:
$("select").each(function(){
$(this).IELongDropDown();
});
Or obviously on a per element bases by id.
Here's the jquery plugin:
(function($) {
$.fn.IELongDropDown = function(cln) {
if (jQuery.browser.msie) { //only IE has problems with long select boxes
var el = this;
var previousWidth = el.width();
var divWrapper = "<div style='padding:0;margin:0;overflow:hidden;width:"+ previousWidth +"px'></div>";
el.wrap(divWrapper);
var newWidth = el.width("auto").width();
el.width(previousWidth);
if(newWidth > previousWidth) {
el.bind("mousedown", function(){ return el.width("auto").focus(); });
el.bind("blur", function(){ return el.width(previousWidth); });
el.bind("change", function(){ return el.width(previousWidth); });
}
}
return this;
};
})(jQuery);
Hope this helps someone
I think that you need to return true from your event handlers (click, blur, etc.) so after your handler executes, the browser continues to propagate the event and open the select.
It is similar with href links, if they have an onclick handler and the handler returns false, the link is not followed (the browser stops the event after your handler executes).
EDIT: Based on your comment and answer, it seems that your handler gets the first chance to execute only after the browser decides to open the box.
I suggest that you try the focus event handler, it might get a chance to run earlier than the click handler and perhaps before the browser actually opens the box. It is also more consistent (applies both to mouse and keyboard navigation).
I prefer to set my CSS in a CSS file and then "addClass" but even so, your code (portion)
$('select').blur(function(){
$(this).css({
'position' : 'relative',
'width' : original_width
});
});
$('select').blur(function(){
$(this).css({
'position' : 'relative',
'width' : original_width
});
});
seems to be a duplicate
I would make it:
$('select').blur().css({
'position' : 'relative',
'width' : original_width
});
Not sure you really even need the .blur() here what with the .change() event (try taking it out see see if that addresses your issue...I use select often on IE and do not seem to have an issue.
Okay, I found another way fixing this problem.
Here is the fix:
Please give me feedback! I'm kind of proud on myself ;)
$(document).ready(function() {
if (jQuery.browser.msie) {
select_init();
}
});
function select_init () {
var selects = $('select');
for (var i = 0; i < selects.length; i++) {
_resizeselect.init(selects[i]);
}
}
var _resizeselect = {
obj : new Array(),
init : function (el) {
this.obj[el] = new resizeselect (el);
}
}
function resizeselect (el) {
this.el = el;
this.p = el.parentNode;
this.ht = el.parentNode.offsetHeight;
var obj = this;
this.set = false;
el.onmousedown = function () {
obj.set_select("mousedown");
}
el.onblur = function () {
obj.reset_select("blur");
}
el.onchange = function () {
obj.reset_select("change");
}
}
resizeselect.prototype.set_select = function (str) {
if (this.set) {
this.set = false;
return;
}
this.el.style.width = "auto";
this.el.style.position = "absolute";
this.p.style.height = this.ht + "px";
this.p.style.zIndex = 100;
this.set = true;
this.el.focus();
}
resizeselect.prototype.reset_select = function (str) {
this.el.style.width = "";
this.el.style.position = "";
this.p.style.height = "";
this.p.style.zIndex = 1;
this.set = false;
window.focus();
}
The mousedown event is raise before the click event :
first mousedown raise -> set the width to 'auto' (if the state of the dropdown is 'close')
click raise -> store in a var the state of the dropdown : 'open'
We select a value, the second mousedown is raised : nothing to do
click raise -> we need to restore the original width of the dropdown and change the state of the var to : 'close'
The blur and change event are needed to close the dropdown if the user clicked outside the dropdown.
Here the complete solution with Brendan's code :
(function ($) {
var open = {}
$.fn.IELongDropDown = function (cln) {
if (jQuery.browser.msie) { //only IE has problems with long select boxes
var el = this;
var id = el.attr('id');
var margin = 2; //Need to set a margin however the arrow is cut
var previousWidth = el.width() + margin;
var divWrapper = "<div style='padding:0;margin:0;overflow:hidden;width:" + previousWidth + "px'></div>";
el.wrap(divWrapper);
var newWidth = el.width("auto").width();
el.width(previousWidth);
if (newWidth > previousWidth) {
el.mousedown(function () {
if (!open[id]) {
el.width("auto");
el.focus();
}
});
el.click(function () {
if (!open[id])
open[id] = true;
else {
open[id] = false;
return el.width(previousWidth);
}
});
el.blur(function () {
open[id] = false;
return el.width(previousWidth);
});
el.change(function () {
open[id] = false;
return el.width(previousWidth);
});
}
}
return this;
};
})(jQuery);
Call the function :
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('#mydropdownlist').IELongDropDown();
});
</script>
you can not open the select list but you can do it by changing the size of theselect list on click or any other event you want
$("#drpdwn").mousedown(bodyevent);
function bodyevent()
{
console.log("size changed");
$(this).attr('size',3);
}
$("#drpdwn").focus(function()
{
//alert("txt clicked from ");
var $el = $("#drpdwn");
var offset = $el.offset();
var event = jQuery.Event( "mousedown", {
which: 1,
pageX: offset.left,
pageY: offset.top
});
$el.trigger(event);
});
As an alternative you can use the select2 plugin and do the following:
$(element_select).focus();
$(element_select).select2('open').trigger('open');
It worked perfectly for me in Firefox version 79.0
There is an alternate solution i found for this problem. Just add a theme to your select box like Selectize.js it will convert your select box into ul li html tags but works as select box. You can easily hide show ul li's on jquery events.

Categories

Resources