THE CODE
Note: All the functions posted here are inside a same file interface.js.
I added an event listener which is executed every time window resizes:
window.addEventListener("resize",
function(_resize){
_window_resize_handler(_resize);
}
);
When event resize happens the handler function _window_resize_handler() which determines (a) if window is wide enough and (b) if we are on mobile / desktop. Based on this it calls one of the two Gridstack.js initialisation functions (one is for desktop and one for mobile):
function _window_resize_handler(_resize){
// Screen properties
let _dpi = window.devicePixelRatio;
let _sw = screen.width;
let _sh = screen.height;
let _ss = _sw + _sh;
let _ar;
let _sww;
// Window properties
let _ww = window.innerWidth;
// We calculate the aspect ratio in landscape format - this is the only one we need.
if (_sw > _sh){
_ar = _sw / _sh;
}
else{
_ar = _sh / _sw;
}
// We set the longer dimension of the two to be screen width.
if (_sw > _sh){
_sww = _sw;
}
else{
_sww = _sh;
}
// If window width is too narrow we use Gridstack's one-column mode regardless of the device.
// Otherwise we let screen properties decide.
if (_ww < 768){
_gridstack_init_mobile();
}
else if( ((_ar < 1.78) && (_dpi < 2.5 ) && (_sww > 768)) || (_ss > 2000)){
_gridstack_init_desktop();
}
else{
_gridstack_init_mobile();
}
}
The Gridstack.js initialisation functions are like this:
For desktop:
function _gridstack_init_desktop(){
// Create global object "grid" with window.
window.grid = GridStack.init({
acceptWidgets: false,
alwaysShowResizeHandle: true,
animate: false,
auto: true,
// cellHeight: "15.45rem",
// column: 12,
disableDrag: false,
disableOneColumnMode: true,
disableResize: false,
draggable: true,
dragOut: false,
float: true,
handle: '.grid-stack-item-content',
handleClass: 'grid-stack-item-content',
itemClass: 'grid-stack-item',
maxRow: 6,
minRow: 6,
minWidth: 768,
oneColumnDomSort: false,
placeholderClass: 'grid-stack-placeholder',
placeholderText: '',
resizable: {
autoHide: false,
handles: 'n, nw, w, sw, s, se, e, ne'
},
removeable: false,
removeTimeout: 2000,
//row: 6,
rtl: false,
staticGrid: false,
});
grid.column(12);
grid.cellHeight("15.45rem");
}
For mobile:
function _gridstack_init_mobile(){
// Create global object "grid" with window.
window.grid = GridStack.init({
acceptWidgets: false,
alwaysShowResizeHandle: true,
animate: false,
auto: true,
// cellHeight: "15.45rem",
// column: 12,
disableDrag: false,
disableOneColumnMode: false,
disableResize: false,
draggable: true,
dragOut: false,
float: true,
handle: '.grid-stack-item-content',
handleClass: 'grid-stack-item-content',
itemClass: 'grid-stack-item',
maxRow: 72,
minRow: 6,
minWidth: 768,
oneColumnDomSort: false,
placeholderClass: 'grid-stack-placeholder',
placeholderText: '',
resizable: {
autoHide: false,
handles: 'n, nw, w, sw, s, se, e, ne'
},
removeable: false,
removeTimeout: 2000,
//row: 6,
rtl: false,
staticGrid: false,
verticalMargin: "0",
});
grid.column(1);
grid.cellHeight("47.15vh");
}
THE RESULTS
This partialy works but only if inside Chrome dev tools I tweak between screens that all trigger the _gridstack_init_mobile(). These are mostly screens for mobile phones:
When I choose e.g. iPad screen that triggers the _gridstack_init_desktop() something goes wrong during the initialisation and I get 1 column instead of 12 (picture on the left). But if I refresh everything is fine and I get 12 columns (picture on the right):
MY SPECULATION
My speculation is that I need to destroy the grid object (if it exists) before I re-initialize it again as a Gridstack object. This is why I tried to put this part of code at the top of _gridstack_init_mobile() and _gridstack_init_mobile():
if (document.getElementsByClassName('grid-stack').length != 0){
grid.destroy();
}
But I get an error:
interface.js:372 Uncaught ReferenceError: grid is not defined
at _gridstack_init_desktop (interface.js:372)
at _window_resize_handler (interface.js:359)
at interface.js:8
Anyone has any idea?
why do you need to destroy if all you need is change the column number ? (for which there is an API). removeAll(removeDOM = true) would remove gridstack info otherwise.
you can change any property even if there isn't an api grid.opts.maxRow=72 , you just won't have any code execute to a change if one was required until the next action happens.
if there is a bug in the lib you should create a minimal reproduceable case and post it as a bug rather than expect someone to read your stack overflow Q... also you fail to say what rev your are using. Try 2.0.0, and from a glance you are using 12 columns but the grid initially comes out with 1 column - also you can't init the same grid multiple times but you can set column(1), removing the dom elements will nuke everything, and you don't even show what your dom starts with. Also don't init with the options in the world, only non default (hard to read otherwise).
Related
I'm using Owl Carousel 2 on a project with dynamic content with an unlimited amount of slides that can be added.
So there could be an instance where there is only three slides or an instance where there is six.
My desired functionality is that if there is less than four slides (the carousel shows four items at a time), then add the mouseDrag: false and touchDrag: false options.
Here is my JS:
$('.owl-carousel').owlCarousel({
loop:false,
margin:20,
responsive : {
// breakpoint from 0 up
0: {
items: 1,
mouseDrag:true,
touchDrag:true
},
// breakpoint from 480 up
500: {
items: 2,
mouseDrag:true,
touchDrag:true
},
// breakpoint from 768 up
740: {
items: 3,
mouseDrag:true,
touchDrag:true
},
// breakpoint from 1024 up
980: {
items: 4,
mouseDrag:false,
touchDrag:false
}
}
})
So, currently when the viewport is over 1024px wide, it will remove the dragging functionality regardless of how many items there are. Which means you can't see any more than 4 (if there are any).
Thanks,
Jay
Please see this answer you can alter to fit what you need.
http://stackoverflow.com/a/33252395/3794783
here is my code for V2 with that in use:
Notice I use the variable value based on the item_count and if 1 only of .item exists, then apply the "false" to: loop:true_false, nav:true_false ..
$(function () {
var owl_instance = $('.sectionlist .owlcarousel');
var item_count = parseInt(owl_instance.find('.item').length);
var true_false = 0;
if (item_count <=1) {true_false = false;} else {true_false = true;}
//
// control nav visiblity thumbs shown vs thumbs allowed visible
// see: http://stackoverflow.com/a/33252395/3794783
//
owl_instance.on('initialized.owl.carousel resized.owl.carousel', function(e) {
$(e.target).toggleClass('owl-nonav', e.item.count <= e.page.size);
});
owl_instance.owlCarousel({
themeClass: 'owltheme-smallnav',
items:3,
responsive:{
0:{items:1,nav:true},
605:{items:3},
670:{items:3},
1250:{items:3},
1520:{items:3}
},
//margin:0,
navRewind:false, // Go to first/last.
// *****************
loop:true_false,
nav:true_false,
// backport the classes to older used ones
navContainerClass: 'owl-buttons',
dotsClass: 'owl-pagination',
dotClass: 'owl-page',
navText: [
'',
''
],
autoplayHoverPause:true, //false
lazyLoad: true,
dots:true // false
});
});
I have a requirement to create a dragable free-scrolling carousel, which I can do with the likes of http://flickity.metafizzy.co/ or http://idangero.us/swiper/. However neither of these allow me to specify an initial movement. Is it possible to simulate a click-drag on these carousels to 'give them a spin'?
Something like:
$('.home-map-wrapper').trigger('mousedown').trigger('mousemove', { clientX: 0, clientY: 0 }).trigger('mousemove', { clientX: 10, clientY: 0 });
Update 1
I've created a fiddle with Flickety to demonstrate. How do I give this an initial movement?
https://jsfiddle.net/sprintstar/b34w9uec/
Update 2
I want it to move initially like you've grabbed it and given it a gentle spin. But I don't want it to auto advance, like with 'autoPlay'. Unfortunately Flickerty offers no such configuration.
You do not have to use events to launch your carousel using flickity,
You can simply:
Retrieve your Flickity instance
Specify a velocity for your carousel
Specify that you are in freeScrolling mode (and not scrolling toward a specific position)
Launch animation
Code
function initFlickety() {
var flickityElement = $('.home-map-wrapper').flickity({
freeScroll: true,
wrapAround: true,
prevNextButtons: false,
pageDots: false,
freeScrollFriction: 0.00
});
var flickity = flickityElement.data("flickity"); // [1]
flickity.velocity = -1; // [2]
flickity.isFreeScrolling = true; // [3]
flickity.startAnimation(); // [4]
}
Fiddle
https://jsfiddle.net/b34w9uec/6/
If I understood correctly you want to have an initial movement on load.
I have tried setting autoPlay to a specific value on plugin initialization like this:
$('.home-map-wrapper').flickity({
autoPlay: 1000,
freeScroll: true,
wrapAround: true,
prevNextButtons: false,
pageDots: false,
freeScrollFriction: 0.00
});
Check this Fiddle
I don't understand how to close a modal or an element with PhanthomJS using sendEvent().
For example I tried to do it using the code below or using CaperJS click and clickLabel and many others things but it's not working.
var webpage = require('webpage').create();
var url = 'http://sourceforge.net/';
webpage.viewportSize = { width: 1280, height: 800 };
webpage.render("test1.png");
webpage.onLoadFinished = function(status) {
var coords = webpage.evaluate(function() {
var firstLink = document.querySelector('a.btn');
return {
x: firstLink.offsetLeft,
y: firstLink.offsetTop
};
});
console.log(coords.x);
console.log(coords.y);
webpage.sendEvent('mousedown', coords.x, coords.y ,'left');
};
webpage.open(url,function(){
webpage.render("test2.png");
phantom.exit()
});
Here is the element I would like to skip.
The offsetLeft and offsetTop only give the offset based on a parent element. You would have to sum all the element offsets up to the root node. That's at least what CasperJS does.
If this notice is static, you can determine the coordinates once and use them every time. Based on the screenshot (444,330) seems good as a replacement for coords.x, coords.y.
You can also simply use a synthentic mouse click as described here which is what CasperJS does, but in combination with a specific position. This is a plain synthetic click:
function click(el){
var ev = document.createEvent("MouseEvent");
ev.initMouseEvent(
"click",
true /* bubble */, true /* cancelable */,
window, null,
0, 0, 0, 0, /* coordinates */
false, false, false, false, /* modifier keys */
0 /*left*/, null
);
el.dispatchEvent(ev);
}
Also, you have two callbacks (onLoadFinished and function in webpage.open) for when the page is loaded. You should have only one, so you don't run into problems when when one of them is called. After you click, it's best to wait a little with setTimeout and let the page change before taking the screenshot.
I need to add a jquery ui slider to each cell of slickgrid. Number of records is over 10,000 with over 150 columns. The problem is that the initial set of sliders are rendered fine but as I scroll (left or right), they disappear. Somehow, the grid is not getting invalidated for those cells. I am using the following formatter on the column:
SliderFormatter = function (row, cell, value, colDef, dataContext) {
var html = "<div class='mySlider' id='slider_" + dataContext['id'] + "'></div>" + value;
return html;
}
and invoking the slider from my document.ready callback.
Any help will be appreciated. Thanks in advance !
SlickGrid renders only what's visible in the viewport, plus a small buffer. As you scroll, rows/cells are dynamically added and removed.
What this means for your case, is that when you initialize the slider widget in your document.ready callback, you're only initializing a tiny portion of them, and the ones that did get initialized, don't get re-initialized when the cells they are in are removed and recreated by SlickGrid.
SlickGrid doesn't allow you to use jQuery widgets like the slider in cells and requires that formatters output pure HTML in order to make it hard to implement the grid in a way that will slow it down. (I won't get into my reasoning behind that admittedly controversial decision.)
My advice here is to avoid using the jQuery UI slider here. It is simply not scalable or performant enough. Without virtualization, what you're trying to do is impossible - initializing 100 sliders is going to be really slow; initializing 10'000 x 150 of them is out of the question. With virtualization, you'll need to initialize and destroy them on the fly as you're scrolling around, and that's just too slow to scroll smoothly.
Consider using an HTML5 range input - <INPUT type="range">. It's supported by all major browsers with the exception of IE <10. See http://caniuse.com/#feat=input-range.
I've created an example using SlickGrid's async post-render option. #Tin is probably right that it would be better to use the native <input type="range"> but just in case you need to support older browsers here's how you can do it.
function waitingFormatter(value) {
return '<div class="slider"></div>';
}
function renderSlider(cellNode, row, dataContext, colDef) {
var cell = $(cellNode);
cell.find('.slider').slider({
value: dataContext.value,
slide: function(e, ui) {
data[row].value = ui.value;
cell.prev().html(ui.value);
}
});
}
var grid;
var data = [];
var columns = [
{ id: "title", name: "Title", field: "title", sortable: false, width: 120, cssClass: "cell-title" },
{ id: "value", name: "Value", field: "value", sortable: false, editor: Slick.Editors.Integer, width: 40, validator: requiredFieldValidator },
{ id: "chart", name: "Slider", sortable: false, width: 425, formatter: waitingFormatter, rerenderOnResize: true, asyncPostRender: renderSlider }
];
var options = {
editable: true,
enableAddRow: false,
enableCellNavigation: true,
asyncEditorLoading: false,
enableAsyncPostRender: true
};
$(function () {
for (var i = 0; i < 500; i++) {
var d = (data[i] = {});
d["title"] = "Record " + i;
d["value"] = Math.round(Math.random() * 100);
}
grid = new Slick.Grid("#myGrid", data, columns, options);
})
Im having a bit of trouble of getting a Royal Slider working in a lightbox - If you take a look at this page: http://www.wearewebstars.dk/frontend/Test/boerneunivers2.html - And then click the arrow, where it says "Hvad er Myanmar" - Then it opens a lightbox with a gallery - However, the container of thumbnails only get a width of 36px - But the if I resize the window, then it gets the full width of all the thumbnails, and places the thumbnails correctly - Any ideas? I've tried resizing the window programmaticly, but cant get it to work:
The script I have is:
$(".toggle-gallery-8").on("click", function(event){
$('#gallery-8').royalSlider({
fullscreen: {
enabled: true,
nativeFS: true
},
controlNavigation: 'thumbnails',
autoScaleSlider: true,
autoScaleSliderWidth: 960,
autoScaleSliderHeight: 850,
loop: false,
imageScaleMode: 'fill',
navigateByClick: true,
numImagesToPreload:5,
arrowsNav:true,
arrowsNavAutoHide: true,
arrowsNavHideOnTouch: true,
keyboardNavEnabled: true,
usePreloader: true,
fadeinLoadedSlide: true,
globalCaption: true,
globalCaptionInside: false,
updateSliderSize: true,
thumbs: {
appendSpan: false,
firstMargin: true,
}
});
$('#gallery-8').royalSlider('updateSliderSize', true);
/*if($(".window.fade.in").length() > 0){
$(".window").trigger("resize");
}*/
});
Looking on the developer site I found that it's a known issue that sometimes happens.
If slider size is dynamic: try to resize your browser, if after
resizing layout looks correctly - this is the issue.
If slider size is static: change size of root slider element via
Chrome Web Inspector or Firebug and resize browser window. Or just run
jQuery('.royalSlider').royalSlider('updateSliderSize', true); in
console and see if it fixes your problem.
Doc: http://help.dimsemenov.com/kb/royalslider-jquery-plugin-issues/slider-content-area-shrinks
You can try to call updateSliderSize method:
setTimeout(function () {
$('.royalSlider').royalSlider('updateSliderSize', true);
}, 500)
after the slider definition, the setTimeout is needed to handle a little timing issue.