I have a slider I have implemented on my site and wanted to land on a specific value when clicking on a link on another page:
Here is the script and the parameter I would like to change:
$("#screeningSlider").ionRangeSlider({
hide_min_max: true,
keyboard: true,
from: 20,
min: 1,
max: 2000,
step: 0,
grid_num: 4,
prettify_separator: ",",
postfix: " Units",
max_postfix: "+",
force_edges: true,
});
So when on another page, I'd like to click on a button that would allow me to land on this page, But the parameter FROM to be 10 instead of the default value above. This should only occur when selecting from that specific button.
Here is my site that has the slider: http://therrd.com/screening.html#tenant-Screening
Sharing JavaScript values between pages isn't really possible without storing it in some other form, and then parsing it back into JavaScript.
You could use URL parameters and then parse the incoming URL and import the default from value from there.
<a href='http://www.yoursite/?from=10'>Referral </a>
The downside to this is, obvious, anyone could just peek at your URL and then try and game your system (think what may happen if they set it to ?from=0 and you didn't protect against that). You'd also need to protect against injection attacks.
You could use localStorage to set a key after they've clicked that specific button, and then check localStorage for that key when loading the main page to get the expected default from value.
Set the value on click for the special link:
$('#link').on('click', function(){
localStorage.setItem('fromValue', 10);
});
And retrieve it on load for the resulting page:
var fromValue = localStorage.getItem('fromValue')
if (fromValue) { /* adjust the slider's default from value*/ }
If you don't want to use server side for that, you can do it this way
[EDITED]
1 - set the link
Go
2 - set your function in yourpage.html
vals = {max: 100, min: 0, def: 20} //use your own values here for max min and def
var param = window.location.href.split("slide=");
slide = isNaN(param[param.length - 1]) ||
param[param.length - 1] > vals.max ||
param[param.length - 1] < vals.min ? vals.def : param[param.length - 1];
//check if there is a url param, if it's a number and if it's in range
$("#screeningSlider").ionRangeSlider({
hide_min_max: true,
keyboard: true,
from: slide,
min: 1,
max: 2000,
step: 0,
grid_num: 4,
prettify_separator: ",",
postfix: " Units",
max_postfix: "+",
force_edges: true,
});
Related
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).
So I have a simple JQuery UI range slider with two handles, as shown in this JSFiddle.
HTML
<p class="results-val">
<span class="min-val">0 </span>to
<span class="max-val"> 30</span> days
</p>
<div id="slider"></div>
JS
$(function(){
$( "#slider" ).slider({
range: true,
min: -60,
max: 60,
step: 5,
values: [ 0, 30 ],
slide: function(event, ui) {
$(".min-val").text(ui.values[0] + " ");
$(".max-val").text(" " + ui.values[1]);
}
});
});
In practice, this slider acts as a filter for our Dashboard application, scoping data shown regarding the user's results based on the range of day values.
Via Google Analytics, we want to track different permutations of handle positions. For clarity, when I say permutations, this is what I mean:
"0 to 30 days" is one permutation.
"-5 to 15 days" is another permutation.
"-40 to 0 days" is another permutation.
And so there are tons of permutations.
My idea for this is to have two events, one for each slider handle, with the handle's current step position as the value being passed:
Category: Filtering,
Action: Adjustment,
Label: leftHandle,
Value: stepPos
Category: Filtering,
Action: Adjustment,
Label: rightHandle,
Value: stepPos
However, there's a problem here. While this approach will indeed report an Average Value for each handle individually, we want to see both values together. As stated above, it's important for us to know the most popular "permutations", with a single permutation consisting of both a left handle position value and a right handle position value.
If anyone has suggestions on how to set this logic, that would be wonderful. Thank you.
You can stuff both values into a comma separated string
You can debounce the slider event to only record values that the user keeps for more than a second or two.
var globalLeft, globalRight;
$(function(){
$( "#slider" ).slider({
range: true,
min: -60,
max: 60,
step: 5,
values: [ 0, 30 ],
slide: function(event, ui) {
$(".min-val").text(ui.values[0] + " ");
$(".max-val").text(" " + ui.values[1]);
globalLeft = ui.values[0];
globalRight = ui.values[1];
$.debounce(1300, doPingGa)
}
});
});
function doPingGa() {
ga('send', 'event', 'Filtering', 'RangeAdjust', globalLeft+','+globalRight);
}
If you use the code with the default buttons:
Ext.Msg.show({
title:'Save Changes?',
msg: 'You are closing a tab that has unsaved changes. Would you like to save your changes?',
buttons: Ext.Msg.YESNOCANCEL,
icon: Ext.Msg.QUESTION
});
the buttons on the window are in the order yes - no - cancel. I would like them in the order cancel - no - yes for consistency in my app. Is there a way to add a different configuration or change this for my needs?
Default buttons is simply created within Ext.window.MessageBox.makeButton() private method based on Ext.window.MessageBox.buttonIds config and show / hide based on bitmask buttons: Ext.Msg.YESNOCANCEL.
So we just have to override buttonIds config and bitmasks:
Ext.define('Ext.overrides.MessageBox', {
override: 'Ext.window.MessageBox',
OK: 1, //0001
CANCEL: 2, //0010
NO: 4, //0100
YES: 8, //1000
OKCANCEL: 3, //0011
YESNO: 12, //1100
YESNOCANCEL: 14, //1110
buttonIds: [
'ok', 'cancel', 'no', 'yes'
]
});
Ext.Msg / Ext.MessageBox is singletones and initially defined as instance of Ext.window.MessageBox before our override (check last lines of Ext.MessageBox code).
So we have to override Ext.Msg / Ext.MessageBox aswell:
Ext.Msg = Ext.MessageBox = new Ext.window.MessageBox();
Check this simple fiddle.
I have two knobs, I would like to control dynamically the value of the first one when moving the second one.
so far I have:
(First Knob)
$('#inf-knob').knobRot({
classes: ['inf-knob'],
frameWidth: 250,
frameHeight: 250,
frameCount: 100,
detent: false,
discreteSteps: false,
stepCount: 0,
minimumValue: 0,
maximumValue: 2,
dragMultiplier: 0.01,
hideInput: true,
});
$('#inf-knob').on('knobdrag', function(e){
//called until mouse button released
var dial = (500 * $('#inf-knob').val()).toFixed(1);
document.getElementById('freqmain').value = dial + " Hz";
document.getElementById('freqmain2').value = dial;
});
(Second Knob Should Change the first one dynamically when moved)
$('#black-knob').on('knobdrag', function(e){
gainNode.gain.value = this.value;
console.log(this.value * 2);
$('#inf-knob').val(this.value * 2);
});
I have also tried using:
document.getElementById('inf-knob').value = this.value;
with no results.
What am I Missing?
Thanks
As the Document of KnobRot states , you should use :
To return the value of the specified knob:
$('myselector').knobRot('get')
To set the value of the specified knob, or knobs (will work with a collection):
$('myselector').knobRot('set', value)
And then you need to trigger KnobRot refresh. So in your case you can use it as :
$('#black-knob').knobRot({
}).on('knobdrag', function(e){
console.log(this.value * 2);
$('#inf-knob').knobRot('set', this.value);
$('#inf-knob').trigger('knobrefresh');
});
And , here is the Working JsFiddle Demo
P.S
The Fiddle demo doesn't show the graphical icon of Knob as i
couldn't figure out all the inclusion required by KnobRot. But , you
can drag hover below the text-field and drag when a expand cursor
shows up.
I have never used such type of plugin.And the plugin documentation
seems to be poor and not frequently updated. Why not use a different
plugin fore-say jQuery-Knob demo
and code base.
I have a readonly jQuery Knob. I have been able to add units to the numeric display (as per How to display units with Jquery Knob ), but the foreground (ie. graphical value indicator) of the dial is no longer displayed when the page is reloaded.
Here's my HTML:
<input class="knob" id="workload" data-angleoffset=-125 data-anglearc=250 value="{{ workload }}" >
( {{ workload }} is a floating point Django template value - it is being substituted correctly )
Inside my jQuery ready function, I have:
if (jQuery().knob && ! App.isIE8()) {
// Workload Indicator
$(".knob").knob({
'dynamicDraw': true,
'min': 0, 'max':100,
'thickness': 0.2,
'tickColorizeValues': true,
'readOnly': true,
'skin': 'tron',
'fgColor': '#F00',
'inputColor':'#3D3D3D',
'bgColor': '#3D3D3D',
'width' : 150,
'draw' : function () {
$(this.i).val( parseInt(this.cv) + '%');
}
});
}
fgColor was originally set from the template value, but the above code with a hard-coded fgColor produces the same result.
Commenting out the draw callback works as expected: The knob is drawn complete with a numeric value in the middle and a red colored indicator on the outside arc.
Uncommenting the draw fixes the numeric formatting (no decimal points + a percentage sign). The numeric formatting remains correct for initial display and on re-load.
However the red arc only appears on the initial display - it disappears when the page is re-loaded!
So what is going on? Is draw over-riding jquery-knob's own canvas draw method? If so, how can I call the graphical draw part?
I was able to use this:
$('.knob').val(0).trigger('change').trigger('draw');
Here is the solution, sent to me by Sally Maughan (not of this parish):
$(".knob").each( function () {
this.value = Math.round( this.getAttribute('value') );
}).knob({
'dynamicDraw': true,
'min': 0, 'max':100,
'thickness': 0.2,
'tickColorizeValues': true,
'readOnly': true,
'skin': 'tron',
'fgColor': wcol,
'inputColor':'#3D3D3D',
'bgColor': '#3D3D3D',
'width' : 150,
'draw' : function () {
this.i.val( this.cv + '%');
}
});
The above version uses a new value from the HTML with each reload.
If you want to keep the same value through the reload, then Sally suggests replacing the this.value assignment with:
this.value = Math.round( this.value.replace('%','') );