How to identify the main global object for Vanilla Picker? - javascript

Vanilla Picker is an absolutely fantastic color picker (example one, example two). However the documentation is a bit lacking. I know how to initialize though I don't know how to identify whatever global object (besides Picker) so I do not know how to access the show(), hide() and/or movePopup(options, open) methods.
The code I've come up with below at least prevents additional popups beyond one-per-element. However it would make more sense (and waste less memory) to simply use the movePopup() method though again I do not know what parent object to refer to. If I console.log(Picker); and looking through the events in the inspector tools of Waterfox and Chrome has me a bit lost. I also have to click twice initially for the popup to be displayed.
How do I identify the global / primary object which I can then use movePopup to only initialize a single Picker with Vanilla Picker?
No frameworks or libraries, except of course of Vanilla Picker itself.
JavaScript
// See URL for Vanilla Picker code:
// https://unpkg.com/vanilla-picker#2.8.0/dist/vanilla-picker.min.js
window.onclick = function(event)
{
if (event.target.hasAttribute('data-color') && event.target.getAttribute('data-color')[0] == '#')
{
console.log(event.target.getAttribute('data-color'));
var picker = new Picker({alpha : true,
color: event.target.getAttribute('data-color'),
editor : true,
editorFormat : 'rgb',
onChange: function(color)
{
event.target.setAttribute('data-color',color.rgbaString);
event.target.style.backgroundColor = color.rgbaString; console.log(color);
},
//onDone: function(color) {console.log(color);},
parent : event.target,
//popup : 'bottom'
});
}
}
HTML
<div data-color="#f00" id="color1">Color 1</div>
<div data-color="#0f0" id="color2">Color 2</div>
<div data-color="#00f" id="color3">Color 3</div>

As you instantiate an instance of Picker you assign it to a variable you can reference it through. If this variable is defined in the global scope, you can access this instance and thus all of its methods from anywhere in your code.
Here's a simple example, where we re-use the same Picker for two different DIVs:
var picker = new Picker();
function changePicker(e) {
picker.movePopup({
parent: e.currentTarget
}, true);
}
document.getElementById("divA").addEventListener("click", changePicker);
document.getElementById("divB").addEventListener("click", changePicker);
picker.onDone = function(color) {
this.settings.parent.style.backgroundColor = color.rgbaString;
};
<script src="https://unpkg.com/vanilla-picker#2.8.0/dist/vanilla-picker.min.js"></script>
<div id="divA">TestA</div>
<div id="divB">TestB</div>
This will set backgroundColor of a DIV as soon as the done button of the picker is pressed. If you take a look at the onDone callback function, you'll notice this.settings. This is an object returned by the picker itself. Among other things it returns the HTML element which is currently associated with the picker - this.settings.parent.

Related

JS Access Method from outside of script file

This one might be a silly question but I really need to fix a tiny slider issue for it's autoplay.
The problem is, are there any way of accessing already instanced object from outside of the script file itself? Note: without knowing the variable / const name of it too.
Example:
Someone from previous Dev team made a gallery of TNS / Tiny Slider like below:
var someName = tns({
container: '.carousel',
items: 3,
autoplay: true,
});
basically it just creating a tns instance from that container. In browser, it shows something like this
<div class="carousel tns-slider">
<div class="tns-item">...</div>
<div class="tns-item">...</div>
...
</div>
The problem is, the code for building that someName tns is from external url that I don't know where is it. Also, I don't know what actually the "someName" variable's name are, so it's already declared there instanced and working properly, I just need to disable the autoplay.
I've tried from documentation from https://github.com/ganlanyuan/tiny-slider
However, it always show how to destroy() or stop() or play() if I know the name of the instanced var (the "someName") while currently I don't have any access to the file nor knowing the path, I just asked to update via new JS file called updates-scripts.js. This is also demonstrated on codepen and other tutorials.
Are there any way of me to access method of it via let say jQuery('.carousel') or documentQuerySelector?
Thank you
This can be done by monkeypatching TNS. Add a setter for window.tns before the library loads. Once the library loads and assigns to the window, invoking the setter, you can assign something else to the window that intercepts the window.tns call that the external script (that you don't have any control over) uses.
Then simply access the .container property of the object passed in, and do whatever you need to do with it:
// Example code from the external script you have no control over
var slider = tns({
container: '.my-slider',
items: 3,
slideBy: 'page',
autoplay: true
});
<script>
// Insert your monkeypatching script here, before anything else
Object.defineProperty(window, 'tns', {
set(tns) {
// Delete this setter
delete window.tns;
window.tns = function(...args) {
const container = args[0]?.container;
console.log('container:', container);
return tns.apply(this, args);
};
},
configurable: true
});
</script>
<script src="https://cdn.jsdelivr.net/npm/tiny-slider#2.9.3/dist/tiny-slider.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tiny-slider/2.9.3/tiny-slider.css">
<div class="my-slider">
<div>foo</div>
<div>bar</div>
<div>baz</div>
</div>

GridStack- Setting the static grids

I am trying to make the grids static. No movement at all.
I tried:
var options = {
staticGrid: true,
};
$('.grid-stack').gridstack(options);
and also this
var options = {
setStatic: true,
};
$('.grid-stack').gridstack(options);
and this
var options = {
staticGrid: true,
};
$('.grid-stack').gridstack(options);
$('.grid-stack').data('gridstack').setStatic(true);
None of them seems to work, I used this link for documentation.
They have also mentioned a method setStatic but there are no examples of usign this method.
According to the Gridstack docs the staticGrid:true parameter is correct if you want to initialise and define the grid as STATIC at startup (your first method).
The SetStatic(true) is a function you can call on for toggling this state programatically.
If you view the source code live you will see a new CSS class has been added to the grid wrapper DIV; a class called 'grid-stack-static'. The appearance of this class confirms the parameter option staticGrid:true has been accepted and actioned.
BUT as I found myself (with v0.30 of the library), grid widgets in my initialised grid are still resizable and movable. In my opinion this suggests a bug.
You can lock down movement and resizing at a widget item level by using the item attributes data-gs-no-resize="yes" and data-gs-no-move="yes".
Seems counterproductive to have to do this if you have said 'static' already.
I have lodged an issue on Github to query this behaviour.
BTW it has been suggested to call on and use the setStatic( true ) function after grid init; as a temporary fix for this bug. Which was your third method - AND this worked for me.
Only difference between your 3rd method and mine is the function is wrapped in a document.ready function (and I am using $=jquery shortcut for convenience/compatibility on my system).
Worked:
(function ($) {
// Shortcut $=jquery
$(document).ready(function () {
// start grid
$(function () {
var options = {
staticGrid:true
};
$('.grid-stack').gridstack(options);
$('.grid-stack').data('gridstack').setStatic( true );
});
// END DOC READY
});
// SHORTCUT FIX
})( jQuery );
Just set the attribute gs-static="true"on the grid-stack's parent Grid element (on which gridstack has been initialized).
<div class="grid-stack" gs-static="true">
<div class="grid-stack-item">
<div class="grid-stack-item-content">Item 1</div>
</div>
<!-- .. and so on -->
</div

Can't find element using UI hash in Marionette Layout

I'm not sure why I can't get the button element using my UI hash. This is what my Layout looks like:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
ui: {
btnSave: "#btnSave"
},
events: {
"click #ui.btnSave": "onSave"
},
onInitialize: function () {
this.listenTo(App.vent, "DisableSaveButton", function(val) {
this.disableSaveButton(val);
},this);
},
disableSaveButton: function () {
this.ui.btnSave.prop("disabled",val).toggleClass("ui-state-disabled",val);
},
onSave: function () {
alert("saved!");
}
})
In VS2013, when my breakpoint hits the line inside disableSaveButton method, I entered $("#btnSave") into the Watch window and I was able to get the element back. I could tell because it had a length of 1. From this, I know the button is rendered. However, if I enter this.ui.btnSave into the Watch window, I would get an element with length of 0.
My BaseLayout object is basically a custom object extended from Marionette.Layout
Marionette version: 1.8.8
Any ideas why I can't find the button element using this.ui.btnSave?
Thanks in advance!
Got some help from a coworker and the issue might be because the element is out of scope. Basically, inside the Layout object, 'this' does not contain the element. We were able replace 'this.ui.btnSave' with '$("#btnSave",this.buttonset.el)' and that works fine. buttonset is the region that actually contains the html element.
This seems like an inconsistency because even though the ui hash didn't work, the click event utilizing the ui hash did work.
UPDATE 6/3/2015:
Another coworker of mine provided a better solution. Basically, in my Layout I use a display function to display my view. It looks something like this:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
display: function() {
$(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
}
})
Basically, I'm saying to set the html of my region, which is this.buttonset.el, to my template's html. As of now, my layout doesn't know any of the elements inside the region. It just contains a region which displays the elements. So there is some sort of disconnect between my layout and the elements in my region.
The correct solution, as opposed to my earlier workaround, is to simply add the following line of code at the end:
this.bindUIElements();
From Marionette Annotated Source:
This method binds the elements specified in the “ui” hash inside the
view’s code with the associated jQuery selectors.
So this final code looks like this:
Layout: App.Base.Objects.BaseLayout.extend({
// Rest of the code left out for brevity
display: function() {
$(this.buttonset.el).html(_.template($("#buttonset-view").html(), {"viewType": viewType}));
this.bindUIElements();
}
})
With this, I was able to finally able to retrieve my element using this.ui.btnSave.

Get Id of TitlePane programatically defined to show/hide

I am very new to Dojo and this is what I am trying to do. I have a titlepane which is programatically declared using the code below:
var pane = this._createTitlePane(config.widgets.title, config.widgets.position,
config.widgets.open);
_createTitlePane: function (title, position, open, optclass) {
var tp = new TitlePane({
title: title,
open: open
}).placeAt(this.sidebar, position);
domClass.add(tp.domNode, 'titlePaneBottomFix titlePaneRightFix');
if (optclass) {
domClass.add(tp.domNode, optclass);
}
tp.startup();
return tp;
},
Later I am trying to hide this title pane when a button is clicked using esri.hide. My question is how do I get a reference to this title pane? There's no Id when it is defined.
When I look in the chrome debugger, I see the below line highlights the widget
<div class="titlePaneBottomFix titlePaneRightFix dijitTitlePane" title="" role="group" id="dijit_TitlePane_1" widgetid="dijit_TitlePane_1">
If I try to do something like esri.hide(dojo.byId("dijit_TitlePane_1")), then it hides the widget. But can I refer to the title pane using this widget Id?
You may want to just give the title pane its own id in the function:
_createTitlePane: function (title, position, open, optclass, paneId) {
var tp = new TitlePane({
title: title,
id: paneId, // TitlePane id here
open: open
}).placeAt(this.sidebar, position);
domClass.add(tp.domNode, 'titlePaneBottomFix titlePaneRightFix');
if (optclass) {
domClass.add(tp.domNode, optclass);
}
tp.startup();
return tp;
}
Then you can refer to it with and hide it with:
esri.hide(dijit.byId("theIdYouGaveIt").domNode);
To understand the difference between dojo.byId and dijit.byId, this link may help.
Also, if you're creating this in your own custom widget, you can also make the title pane a local reference, ie: this.tp = new TitlePane({...}). Anywhere you need to access it from inside the widget, you can simply call "this.tp". Outside of the widget, you can access it using dot notataion: myWidget.tp.doSomething(). Better yet, if you create it declaratively in a template like this: <div data-dojo-type=dijit/TitlePane" data-dojo-attach-point="tp" ...></div>, when the widget is instantiated it will automatically have a handle to "this.tp" via the attach point.

jQuery mobile 1.1.0 slider: JS-object properties access?

EDIT: This could be seen as a pure javascript objects question. The code can be found here:
jquery.mobile-1.1.0.js
I need to access properties of a jQuery mobile JS-object but is not sure how that is possible. In the jquery.mobile-1.1.0.js and mobile.slider is the following (see extend on line 5967):
$.widget( "mobile.slider", $.mobile.widget, {
...
_create: function() {
...
$.extend( this, {
slider: slider,
handle: handle,
valuebg: valuebg,
dragging: false,
beforeStart: null,
userModified: false,
mouseMoved: false
});
Primarily the property I would like to read is the "dragging".
I know i can execute the methods using:
$("#slider").slider("refresh")
Is there a similair way to access the properties?
Thanks
How to react to user dragging the slider, without having to bind mouse-/tap-events, but instead using the JQM functionallity already in place.
To access the "dragging" variable of the JQM slider object I made an extension to the object as follows:
$(document).bind("mobileinit", function(){
$.mobile.slider.prototype.getDragging = function(){
return this.dragging;
};
});
With that in place, I can choose to react to changes only done by the user:
$("#slider").live('change',function(){
if($("#slider").slider("getDragging"))){
console.log('User is dragging slider to new value');
}
else {
console.log('Program changed value. (or user typed in visible textbox)') ;
}
});
With the slider textbox hidden, this give me the benefit of:
Using the "change"-event to react to user dragging without being triggered when my program change the slider value.
When my program is going to change the slider value, it can first check that the user is NOT currently dragging the slider.

Categories

Resources