I made one helper for open new popup window on click and I have a problem with setup default values inside object. I need to calculate position for TOP and LEFT position for popup to center new popup. Here is complete code:
/*
$(element).onPopup(options); - Open Popup window
-Ths function open new popup window on your browser
EXAMPLE:
----------------------------------------------
Google
$("a#link").onPopup({
name : "Popup Window",
width : 800,
height : 600
});
OPTIONS:
----------------------------------------------
attr // attribute where is located link
name // name of popup window
width // max width
height // max height
left // position left (px)
top // position top (px)
resizable // resizable 1 or 0
location // display location 1 or 0
fullscreen // open in full screen 1 or 0
scrollbars // display scroll bars 1 or 0
titlebar // display title bar 1 or 0
toolbar // display tool bar 1 or 0
directories // display directories 1 or 0
*/
$.fn.onPopup=function(options){
var s = {
attr : "href",
name : "Popup Window",
width : 700,
height : 600,
left : ($(window).width()/2)-(this.width/2),
top : ($(window).height()/2)-(this.height/2),
resizable : 0,
location : 0,
fullscreen : 0,
scrollbars : 1,
titlebar : 0,
toolbar : 0,
directories : 0
},
$element = this;
s = $.extend(s,options);
$element.on("click",function(e) {
e.stopPropagation(); e.preventDefault();
window.open(
$(this).attr(s.attr), s.name, "width="+s.width+", height="+s.height+", directories="+s.directories+", toolbar="+s.toolbar+", titlebar="+s.titlebar+", scrollbars="+s.scrollbars+", fullscreen="+s.fullscreen+", location="+s.location+", resizable="+s.resizable+", top="+s.top+", left="+s.left
);
});
};
And here is where is my problem:
var s = {
/*...*/
width : 700,
height : 600,
left : ($(window).width()/2)-(this.width/2),
top : ($(window).height()/2)-(this.height/2),
/*...*/
},
How to pass width/height to another object to work?
One way is to create the object first then add extra properties that reference other properties in the object
var s = {
attr : "href",
name : "Popup Window",
width : 700,
height : 600,
left : null, //calculated if not user provided
top : null //calculated if not user provided
....
};
// update user settings
s = $.extend(s,options);
// calculate based on actual values
if(s.left === null){
s.left = ($(window).width()/2)-(s.width/2);
}
if(s.top === null){
s.top = ($(window).height()/2)-(s.height/2);
}
Also note you should return this.each(.. and run your business there so you have separate instances when selector includes more than one element as well as make the plugin chainable with other jQuery methods
According to your API in the code comments you want the caller to be able to specify their own left and top positions.
You therefore need to check whether any values have been given at all, and only then calculate the default position based on the configured width and height.
var s = {
... // defaults, *not including* "left" and "top"
};
// override the defaults with the user-supplied options
// NB: no need to re-assign to `s` - `$.extend` overwrites
// the contents of the first parameter
$.extend(s, options);
// then calculate `left` and `top` if they weren't supplied
if (s.left === undefined) {
s.left = ($(window).width() - s.width) / 2;
}
if (s.top === undefined) {
s.top = ($(window).height() - s.height) / 2;
}
Related
I am building a jssor slider dynamically using javascript. The slider is based on the jssor 'carousel' demo. Everything looks correct when displayed, including the navigation arrows at either end of the slider. It will also respond correctly when I swipe left or right with the mouse. The slider, however, does not respond to any clicks on the nav arrows.
One problem I have seen mentioned in other postings is improper nesting of the nav arrows. I don't think that is the problem here. Any help would be most appreciated.
Here is the javascript that builds the slider:
var CpxRowSlider = function(callback) {
var callback;
var indexedImgEl = new Array();
var DEFAULT_H = 110;
var DEFAULT_W = 260;
var outerDivEl = document.createElement('div');
var title = true;
var addNavArrows = true;
var sliderDivEl = null;
var sliderId = "slider_SOLO";
/*
* image set should be an array of key-value pairs where the value is the
* URL of an image and the key will be used as a tag that identifies the
* image in any callback functions.
*/
function create(imageSet) {
/* Slides Container -- */
var rowDivEl = document.createElement('div');
$(rowDivEl).attr("u", "slides");
$(rowDivEl).css({
"cursor" : "move",
"position" : "absolute",
"left" : "0px",
"top" : "0px",
"width" : "780px",
"height" : "110px",
"overflow" : "hidden"
});
for ( var key in imageSet) {
var imgUrl = imageSet[key];
var imgDivEl = document.createElement('div');
var imgEl = document.createElement('img');
imgEl.src = imgUrl;
$(imgEl).attr("u", "image");
imgDivEl.appendChild(imgEl);
// add to row
rowDivEl.appendChild(imgDivEl);
$(imgEl).data("cpxKey", key);
/*
* actions associated with the img....
*/
/*
* click event gets handed off via callback
*/
if ((callback != undefined) && (callback != null)) {
imgEl.onclick = function(evt) {
var targetImg = evt.target;
trace("Click on " + $(targetImg).data("cpxKey"));
callback($(targetImg).data("cpxKey"));
};
}
}
// add slides to a slider...
sliderDivEl = document.createElement('div');
sliderDivEl.id = sliderId
$(sliderDivEl).css({
"position" : "relative",
"left" : "0px",
"top" : "0px",
"width" : "780px",
"height" : "110px"
});
// add to DOM
sliderDivEl.appendChild(rowDivEl);
if (addNavArrows) {
sliderDivEl.appendChild(createNavArrow(true));
sliderDivEl.appendChild(createNavArrow(false));
}
outerDivEl.appendChild(sliderDivEl);
}
function createNavArrow(toLeft) {
var arrowSpan = document.createElement('span');
$(arrowSpan).attr("u", "image");
$(arrowSpan).css({
"top" : "30px",
"width" : "55px",
"height" : "55px"
});
if (toLeft) {
$(arrowSpan).css({
"left" : "5px"
});
$(arrowSpan).addClass("jssora03l");
} else {
$(arrowSpan).css({
"right" : "5px"
});
$(arrowSpan).addClass("jssora03r");
}
return arrowSpan;
}
/*
* Invoked only AFTER the slider has been added to the DOM
*/
function finalize() {
// add to sliders being controlled by jssor
var sliderOptions = getSliderOptions();
var jssor_sliderh = new $JssorSlider$(sliderId, sliderOptions);
}
function getSliderOptions() {
var sliderhOptions = {
/*
* $AutoPlay [Optional] Whether to auto play, to enable slideshow,
* this option must be set to true, default value is false
*/
$AutoPlay : false,
/*
* $PauseOnHover [Optional] Whether to pause when mouse over if a
* slider is auto playing, 0 no pause, 1 pause for desktop, 2 pause
* for touch device, 3 pause for desktop and touch device, default
* value is 1
*/
$PauseOnHover : 1,
/*
* $AutoPlaySteps [Optional] Steps to go for each navigation request
* (this options applys only when slideshow disabled), the default
* value is 1
*/
$AutoPlaySteps : 2,
/*
* $ArrowKeyNavigation [Optional] Allows keyboard (arrow key)
* navigation or not, default value is false
*/
// $ArrowKeyNavigation : true,
/*
* [Optional] Specifies default duration (swipe) for slide in
* milliseconds, default value is 500
*/
$SlideDuration : 300,
/*
* [Optional] Minimum drag offset to trigger slide , default value
* is 20
*/
$MinDragOffsetToSlide : 20,
/*
* [Optional] Width of every slide in pixels, default value is width
* of 'slides' container
*/
$SlideWidth : DEFAULT_W,
/*
* [Optional] Height of every slide in pixels, default value is
* height of 'slides' container
*/
// $SlideHeight: 150,
/*
* [Optional] Space between each slide in pixels, default value is 0
*/
$SlideSpacing : 3,
/*
* [Optional] Number of pieces to display (the slideshow would be
* disabled if the value is set to greater than 1), the default
* value is 1
*/
$DisplayPieces : 3,
/*
* [Optional] The offset position to park slide (this options applys
* only when slideshow disabled), default value is 0.
*/
$ParkingPosition : 0,
/*
* [Optional] The way (0 parellel, 1 recursive, default value is 1)
* to search UI components (slides container, loading screen,
* navigator container, arrow navigator container, thumbnail
* navigator container etc).
*/
$UISearchMode : 0,
// ...................................
// [Optional] Options to specify and enable navigator or not
$BulletNavigatorOptions : {
$Class : $JssorBulletNavigator$, // [Required] Class to
// create navigator instance
$ChanceToShow : 1, // [Required] 0 Never, 1 Mouse Over, 2
// Always
$AutoCenter : 0, // [Optional] Auto center navigator in
// parent container, 0 None, 1 Horizontal, 2
// Vertical, 3 Both, default value is 0
$Steps : 1, // [Optional] Steps to go for each navigation
// request, default value is 1
$Lanes : 1, // [Optional] Specify lanes to arrange items,
// default value is 1
$SpacingX : 0, // [Optional] Horizontal space between each item
// in pixel, default value is 0
$SpacingY : 0, // [Optional] Vertical space between each item
// in pixel, default value is 0
$Orientation : 1
// [Optional] The orientation of the navigator, 1 horizontal, 2
// vertical, default value is 1
}
}
return sliderhOptions;
}
function trace(msg) {
console.log("CpxRowSlider: " + msg);
}
return {
create : create,
finalize : finalize,
getContainer : function() {
return outerDivEl;
}
};
};
UPDATE:
Well, some digging around turned up the "where" but the "why" is still a mystery. The generated HTML should look something like this (minus the "styles" for clarity):
<div id="slider_SOLO" >
<div u="slides">
<div>
<img u="image" src="../foo1.jpg" />
</div>
<div>
<img u="image" src="../foo2.jpg" />
</div>
<div>
<span u="arrowleft" class="jssora03l" ></span>
<span u="arrowright" class="jssora03r"></span>
</div>
The problem is that in the actual HTML page there are TWO elements with the attribute u="slides". The 2nd is the correct one but just before it is another empty div. In other words, the DOM I see when I examine the displayed HTML is more like:
<div id="slider_SOLO" >
<div u="slides"></div>
<div u="slides">
<div>
<img u="image" src="../foo1.jpg" />
</div>
<div>
<img u="image" src="../foo2.jpg" />
</div>
<div>
<span u="arrowleft" class="jssora03l" ></span>
<span u="arrowright" class="jssora03r"></span>
</div>
If I add a similar div to the jssor carousel demo HTML, I get the same behavior (i.e., navigation arrows no longer work).
The problem is that the error (i.e., the extra DIV) is not inserted by my javascript. Rather it seems to be linked to the call
var jssor_sliderh = new $JssorSlider$(sliderId, sliderOptions);
I am wondering if the cause is something in the options I pass in.
Found it! The root cause was indeed my options but not in the way I thought. I was missing the $ArrowNavigatorOptions. The mystery DIV is still being inserted but everything now works correctly.
The take-away lesson for me is that jssor seems to fail quietly in the sense that rather than generate a console message about the missing option it simply did nothing.
I am trying to make my autocomplete menu open above the input box if there is not enough space below the input box to display the menu. The code works fine except for on the initial render.
This means that it always displays at the bottom when:
1. Start searching
2. Click in the field and fire the search for the existing text in field
I have it output the position.my and position.at contents and they both are correct for "above" placement but it still displays below the input box.
I have the function called resize that is binded to window scroll and resize also. The moment you scroll the page, the menu gets positioned correctly. My suspect is that it is positioning before fully rendering.
Code
_renderMenu function hook
// Autocomplete _renderMenu function
$(autocomplete_object)._renderMenu = function( ul, item ) {
var that = this;
jQuery.each( items, function( index, item ) {
that._renderItemData( ul, item );
});
// Make sure the menu is now shown to calculate heights and etc (menu is now rendered, position rendering next)
jQuery(ul).show();
autocomplete.resize(ul, options);
autocomplete.create_dropdown_handlers(ul, options);
}
Resize Function
// Resize function
function resize( ul, options ) {
var height;
// If the height of the results is smaller than the space available, set the height to the results height
var ul_height = 0;
jQuery(ul).find('li').each(function(i, element){
ul_height += jQuery(element).height();
});
// Make the height the full height available below the input box but above the window cut off
// Move the dropdown above the input box if there is not enough room below the input box
var $parent = jQuery("#" + options.name);
var padding = 25; // arbitrary number to prevent dropdown from hitting the window border in either direction
var bottom_distance = autocomplete.getViewportHeight() - ($parent.offset().top + $parent.height()) - padding;
var bottom_limit = 200;
var ul_position = {
my: "left top",
at : "left bottom",
of: $parent,
collision: 'none'
};
height = bottom_distance;
if (bottom_distance < bottom_limit) {
var top_distance = $parent.offset().top - padding;
height = top_distance;
// ----- It is getting here fine! -----
ul_position.my = "left bottom";
ul_position.at = "left top";
}
// We have room to show the entire dropdown results without a scrollbar
if (ul_height < height) {
height = 'auto';
}
// Position below or above parent depending on space
jQuery(ul).position(ul_position);
jQuery(ul).css({height: height == 'auto' ? height : height + 'px'});
}
TLDR:
Jquery position is set to show above input field, but it still shows below?
I ended up having to update the autocomplete object's position value as well as the ul position. I believe the issue was that the initial render would inherit the autocomplete's position variable (Which defaults to showing below the input box).
Here is the new line:
// In the resize function after jQuery(ul).position(ul_position);
$parent.autocomplete("option", "position", ul_position); // Now the rendering is correct!
Resize function addition
function resize (ul, options) {
...
calculate the height and position requirements
...
jQuery(ul).position(ul_position);
$parent.autocomplete("option", "position", ul_position); // <-- Addition to honor position for rendering
}
I am using equalHeightColumns.js to provide a cross browser equal height, which works fine until I need to have 2 sets of equal height.
So at the moment I have:
$(".row").each(function(){
$(this).find(".equalHeight").equalHeightColumns();
});
<div class="row">
<section class="equalHeight"></section>
<section class="equalHeight"></section>
</div>
<div class="row">
<section class="equalHeight"></section>
<section class="equalHeight"></section>
</div>
As you can see I dont want everything with the equalHeight to have the same height only inside the same row.
The problem is that now I need to change the mark up and dont have the row to reference. Is it possible to make this work like the lightbox rel='group2' plugin so that I can group the equalHeight elements via attribute.
E.g: this would be
<section class="equalHeight" rel="group1"></section>
<section class="equalHeight" rel="group1"></section>
<section class="equalHeight" rel="group2"></section>
<section class="equalHeight" rel="group2"></section>
equalHeightColumns.js
/*!
* equalHeightColumns.js 1.0
*
* Copyright 2013, Paul Sprangers http://paulsprangers.com
* Released under the WTFPL license
* http://www.wtfpl.net
*
* Date: Thu Feb 21 20:11:00 2013 +0100
*/
(function($) {
$.fn.equalHeightColumns = function(options) {
defaults = {
minWidth: -1, // Won't resize unless window is wider than this value
maxWidth: 99999, // Won't resize unless window is narrower than this value
setHeightOn: 'min-height', // The CSS attribute on which the equal height is set. Usually height or min-height
heightMethod: 'outerHeight',// Height calculation method: height, innerHeight or outerHeight
delay: false,
delayCount: 100
};
var $this = $(this); // store the object
options = $.extend({}, defaults, options); // merge options
// Recalculate the distance to the top of the element to keep it centered
var resizeHeight = function(){
// Get window width
var windowWidth = $(window).width();
// Check to see if the current browser width falls within the set minWidth and maxWidth
if(options.minWidth < windowWidth && options.maxWidth > windowWidth){
var height = 0;
var highest = 0;
// Reset heights
$this.css( options.setHeightOn, 0 );
// Figure out the highest element
$this.each( function(){
height = $(this)[options.heightMethod]();
if( height > highest ){
highest = height;
}
} );
// Set that height on the element
$this.css( options.setHeightOn, highest );
} else {
// Add check so this doesn't have to happen everytime
$this.css( options.setHeightOn, 0 );
}
};
// Call once to set initially
if (options.delay){
setTimeout(resizeHeight, options.delayCount);
} else {
resizeHeight();
}
// Call on resize. Opera debounces their resize by default.
$(window).resize(resizeHeight);
};
})(jQuery);
If you want an automatic script, you need to do a recursive function like that :
var $all = $('.equalHeight'),
arrEqualH = [];
recursiveFilter()
function recursiveFilter(){
var attr = $all.first().attr('rel');
arrEqualH.push($('[rel='+attr+']'));
$all = $all.not('[rel='+attr+']');
if($all.length) recursiveFilter()
}
$.each(arrEqualH, function(){
this.equalHeightColumns();
})
Fiddle : http://jsfiddle.net/2w9tq/
You could try that:
$(".row").each(function(){
$(this).find(".equalHeight[rel='group1']").equalHeightColumns();
$(this).find(".equalHeight[rel='group2']").equalHeightColumns();
});
I'm working with a custom scrolling div jQuery plugin. I want the div to fill 100% of the width of its parent to change size depending on the browser window size.
The script takes a given width parameter, and uses it throughout the script. The customizable parameters of the script seem to only allow me to specify the width in pixels, as an integer:
$.fn.hoverscroll.params = {
vertical: false, // Display the list vertically or not
width: 1280, // Width of the list
height: 230, // Height of the list
arrows: true, // Display arrows to the left and top or the top and bottom
arrowsOpacity: 0.4, // Maximum opacity of the arrows if fixedArrows
fixedArrows: false, // Fix the displayed arrows to the side of the list
rtl: false, // Set display mode to "Right to Left"
debug: false // Display some debugging information in firebug console
};
I tried quoting the percentage, '100%', but that didn't work. Is there a way to use a percentage here?
If not, is there a way to use a script like the one below, which determines the width of the window, make the script output the width in pixels, and use that integer as the width parameter in the jQuery script?
<script type="text/javascript">
function alertSize() {
var myWidth = 0;
if( typeof( window.innerWidth ) == 'number' ) {
//Non-IE
myWidth = window.innerWidth;
} else if( document.documentElement && ( document.documentElement.clientWidth ) ) {
//IE 6+ in 'standards compliant mode'
myWidth = document.documentElement.clientWidth;
} else if( document.body && ( document.body.clientWidth ) ) {
//IE 4 compatible
myWidth = document.body.clientWidth;
}
//window.alert( myWidth );
}
</script>
For reference, here is the full script of the plugin that I'm using:
http://rascarlito.free.fr/hoverscroll/js/hoverscroll/jquery.hoverscroll.js
If you want the width of the hoverscroll region to be some percentage of a container on ready, you can always use jQuery. Wrap your start-up routine in a ready() expression:
$(document).ready(function() {
var w = $(window).width();
var p = 0.95 /* Your percentage */
$.fn.hoverscroll.params = {
width: w * p, // Width of the list
...
};
// Start your hoverscroll like normal;
});
That ... is just there to indicate "the other stuff goes here." I didn't want to fill the answer up with repetitious code.
Although in normal practice, you would never modify the defaults in place, but pass them as arguments:
$(document).ready(function() {
var w = $(window).width();
var p = 0.95 /* Your percentage */
$('#mylist').hoverscroll({
width: w * p // Width of the list
});
});
Note that I'm only passing in the width; everything else uses the defaults. You only have to set the ones that differ from the defaults-- in this example, I've only set the width.
Regardless of what height argument I use, my window keeps a steady height of about 250px. The console.log statement outputs 600 when I pass 600 to show, e.g. getIFrameWindow().show({height: 600}), so I know my height argument is being passed and received correctly, but my window doesn't render with it's correct height.
getIframeWindow : function () {
return {
show :function(args) {
args=args||{};
win = new Ext.Window({
width :args.width||200,
height :args.height||200,
items :[{
border : false,
xtype : 'iframepanel',
defaultSrc : args.src||'_blank.htm'
}]
});
console.log(win.height);
win.show();
},
try this :
width :args.width * 1.0 ||200,
height :args.height * 1.0 ||200,
args.width and args.height will become numbers