I am using a bootstrap slider on my site using HTML and JavaScript (no Jquery). It is set up pretty much as I want it, with permanent tooltips and values etc.
However, I want to store the value that the user finishes on. I have this working to some extent, IF the user slides the slider. If the user CLICKS on the slider then it doesn't update the value.
Any advice on tracking any kind of interaction?
HTML:
<input id="sliderman1" type="text" data-slider-min="0" data-slider-max="4" data-slider-step="1" data-slider-value="2" data-slider-ticks="[0, 4]"/>
<span id="sliderman1Value">3</span></span>
JS:
var values = ['None', 'Read', 'Speak', 'Test', 'Last'];
var formatter = (index) => values[index];
var slider = new Slider("#sliderman1", {formatter} );
slider.on("slide", function(sliderValue) {
document.getElementById("sliderman1Value").textContent = sliderValue;
});
How about adding an onTouchEnd event listener?
JS
slider.on("onTouchEnd", function(sliderValue) {
document.getElementById("sliderman1Value").textContent = sliderValue;
}
or add it directly to your slider:
HTML
<input ontouchend="myFunction(event)" ... />
Related
After having a few small wins with JS (still very much a learner) I have now inherited a task which is to change a reductive search of sorts.
Users now want to have the search work from a submit button, instead of a keyup after 3rd character. I have completed submit forms before where the form would post, but I have never come across something as complex as this before.
I have had a look through the large JS file, and located the search function which contains the keyup function.
F.initSearch = function(opts){
if(!opts || !opts.ele){
return;
}
if(!opts.start_length){
this.opts.search.start_length = 2
}
this.$search_ele = $(this.opts.search.ele);
if(this.$search_ele.length){
this.has_search = true;
this.searchFn = this.buildSearchFn(opts.fields);
this.bindEvent(opts.ele, 'keyup');
}
};
However, I am having difficulty with changing over from keyup to button click.
This is what I have done:
I have updated the form to include the button
<form>
<div class="searchBox">
<input type="text" id="search" class="search__text-input" placeholder="Search"/>
</div>
<div class="formBox">
<button id="searchbtn">Search</button>
</div>
</form>
I have tried to update the script with some jquery which follows the same pattern
$( "#searchbtn" ).this.bindEvent(opts.ele, 'click');
Lastly, I have attempted to then update the existing - which is now leaving me somewhat defeated:
F.initSearch = function(opts) {
if(!opts || !opts.ele) {
return;
}
if(!opts.start_length) {
this.opts.search.start_length = 2
}
this.$search_ele = $(this.opts.search.ele);
if(this.$search_ele.length) {
this.has_search = true;
this.searchFn = this.buildSearchFn(opts.fields);
// this.bindEvent(opts.ele, 'keyup');
/* Trying to swap keyup for button click */
$( "#searchbtn" ).this.bindEvent(opts.ele, 'click');
}
};
Link to JSFiddle: https://jsfiddle.net/mcmacca002/bo0y3u7p/2/
Clearly I am approaching this wrong, and some guidance would be greatly appreciated.
How to set the value of dimmer element properly?
I have these files. It's a basic structure from example.
index.html
<div class="ui-page" id="dimmer-page">
<div class="ui-content dimmer-content">
<div class="ui-dimmer" id="dimmer"></div>
<input id="slider" type="range" value="50" min="0" max="100">
</div>
<script src="js/dimmer.js"></script>
<script src="js/set_dimmer.js"></script>
</div>
dimmer.js
/* global tau */
(function () {
var page = document.getElementById("dimmer-page"),
elSlider = document.getElementById("slider"),
elDimmer = document.getElementById("dimmer"),
dimmer,
slider,
pageBeforeShowHandler,
pageHideHandler;
pageBeforeShowHandler = function () {
slider = tau.widget.Slider(elSlider);
dimmer = tau.widget.Dimmer(elDimmer);
elSlider.addEventListener("change", onInput, false);
};
function onInput(event) {
var newVal = parseInt(event.target.value),
convertedVal;
dimmer.value(newVal);
}
pageHideHandler = function () {
slider.destroy();
dimmer.destroy();
};
page.addEventListener("pagebeforeshow", pageBeforeShowHandler);
page.addEventListener("pagehide", pageHideHandler);
}());
I have mqtt broker that sends me value which I want to show in this dimmer.
I'v added this file.
set_dimmer.js
function setDimmerValue(value) {
var dimmerElement,
dimmer;
dimmerElement = document.getElementById("dimmer");
dimmer = tau.widget.Dimmer(dimmerElement);
dimmer.value(value);
}
And when I get another value from mqtt I call this function. It shows me the proper value in percents, the brightness of background is proper, but the slider shows its default value, so I want it to work correct. When I leave this page and come back again it shows me the default value, but I want to show the last value I`v set.
Above code presents connection of two widgets Slider + Dimmer.
Dimmer only show value as level of element brightness.
Slider has bound touch control. Method onInput changes dimmer value on the slider change.
So, if you want set value properly you should set Slider value.
function setValue(value) {
var sliderElement = document.getElementById("slider"),
slider;
slider = tau.widget.Slider(sliderElement); // or tau.engine.getBinding(sliderElement)
slider.value(value);
}
I have a problem that i can't fix.
Keyboard doesn't show on input.focus() on IOS
searchMobileToggle.addEventListener('click', function() {
setTimeout(function(){
searchField.focus();
}, 300);
});
I've been looking for a solution with no result, i know this is a frequently unsolved question but i see NIKE (https://m.nike.com/fr/fr_fr/) and FOODSPRING (https://www.foodspring.fr/) doing it on mobile.
So i'm wondering how do they do ?
None of the other answers worked for me. I ended up looking into the Nike javascript code and this is what I came up with as a reusable function:
function focusAndOpenKeyboard(el, timeout) {
if(!timeout) {
timeout = 100;
}
if(el) {
// Align temp input element approximately where the input element is
// so the cursor doesn't jump around
var __tempEl__ = document.createElement('input');
__tempEl__.style.position = 'absolute';
__tempEl__.style.top = (el.offsetTop + 7) + 'px';
__tempEl__.style.left = el.offsetLeft + 'px';
__tempEl__.style.height = 0;
__tempEl__.style.opacity = 0;
// Put this temp element as a child of the page <body> and focus on it
document.body.appendChild(__tempEl__);
__tempEl__.focus();
// The keyboard is open. Now do a delayed focus on the target element
setTimeout(function() {
el.focus();
el.click();
// Remove the temp element
document.body.removeChild(__tempEl__);
}, timeout);
}
}
// Usage example
var myElement = document.getElementById('my-element');
var modalFadeInDuration = 300;
focusAndOpenKeyboard(myElement, modalFadeInDuration); // or without the second argument
Note that this is definitely a hacky solution, but the fact that Apple hasn't fixed this in so long justifies it.
I found a solution, click() didn't work, but i figured it out.
searchMobileToggle.addEventListener('click', function() {
if(mobileSearchblock.classList.contains('active')) {
searchField.setAttribute('autofocus', 'autofocus');
searchField.focus();
}
else {
searchField.removeAttribute('autofocus');
}
});
I was working with vue.js that was removing input autofocus attribute, when the component was loaded.
So i had it on click, but there was another problem, the autofocus only worked once, but combined with focus(), it now work all the time :)
Thanks for your help !
This really drives me/us crazy. It works fine on the Android phone, but something is disabled by the Apple developer. (I understand it's annoying to pop the keyboard when not necessary though).
I accidentally found out that the "popup" module from Semantic-UI fixes this magically.
Note that the solution works for SemanticUI (#semantic-ui team may tell what event makes this work)
Here are how I did:
const [search, setSearch] = useState(false);
const inputRef = useRef(null);
React.useEffect(() => {
if (search) {
inputRef.current.focus();
} else {
inputRef.current.blur();
}
}, [search]);
<div onClick={() => setSearch(true)}>
<Popup
content="Search for Swimmers and Time Standards."
offset={[-500, -1000]}
trigger={<Icon name="search" />}
/>
</div>
{search && <Input ref={inputRef} />}
As you see, I wrapped the trigger Icon with the Popup module, and hide the Popup content by setting the crazy offset. And then it magically works.
See the demo here: https://swimstandards.com/ (check it out on your iPhone)
Angular solution:
on button click we need to create temporary input, append to existing container (close to our input) and focus on it.
btnClicked() {
this.showModal = true;
this.searchBar = this.renderer2.selectRootElement('#searchBar', true);
// 2nd argument preserves existing content
// setting helper field and focusing on it
this.inputHelper = this.renderer2.createElement('input');
this.renderer2.appendChild(this.searchBar, this.inputHelper);
this.inputHelper.focus();
let event = new KeyboardEvent('touchstart',{'bubbles':true});
this.searchBarButton.nativeElement.dispatchEvent(event);
}
after modal/target input is shown, we move focus and remove temporary one:
initiateKeyboard() {
setTimeout(()=> {
this.searchBarInput.nativeElement.focus();
this.renderer2.removeChild(this.searchBar, this.inputHelper);
},180);
}
and template:
<div id="searchBar">
<input type="button" class="button is-link is-light" value="Search" (click)="btnClicked()" (touchstart)="initiateKeyboard()" #searchBarButton>
</div>
You just need to remember that iPhone may zoom screen, so you need to adjust parameters of temporary input.
working solution: https://inputfocus.vercel.app/
Worked in 2022 with ios 16!
OMG, I searched for so long and the above solution won't work for me.
Here is how it worked for me. I wrapped the input in a React FocusLock component. Check this package out: https://www.npmjs.com/package/react-focus-lock
Here is a small example:
<FocusLock>
<Input />
</FocusLock>
There is no legitimate way to do this since iOS kind of wants to only open the keyboard on a user interaction, however you can still achieve this with either using prompt() or using focus() from within a click() event it and will show up.
I am working on Dojo Version 1.8.I have designed one custom widget as below. Its a snippet
<div>
<div>
<input
id ="NZ1",
data-dojo-attch-point = "NZ1"
data-dojo-attch-type = "ecm.widget.ValidationTextBox"
data-dojo-attch-event = "onBlur : makeAllSmall"
/>
</div>
<div>
<input
id ="NZ2",
data-dojo-attch-point = "NZ2"
data-dojo-attch-type = "ecm.widget.ValidationTextBox"
data-dojo-attch-event = "onBlur: makeAllSmall"
/>
</div>
</div>
Here is event handler
makeAllSmall : function(evt){
var currVal=evt.target.value;
currVal = currVal.toLowerCase();
/**Some Other business logic on currVal **/
}
This evt is always coming as undefined . I am quite new to Dojo. Am I missing something in HTML side ? I tried to change HTML as below but not luck
<input
id ="NZ2",
data-dojo-attch-point = "NZ2"
data-dojo-attch-type = "ecm.widget.ValidationTextBox"
data-dojo-attch-event = "onBlur : makeAllSmall"
data-dojo-args="e"
/>
First thing first, is there a typo in the method "onBlurr"? I see there is an extra 'r'. Shouldn't it be "onBlur"?
If you look at the DOJO API documentation for onBlur event, it doesn't pass an event object like what you are expecting
onBlur()
Defined by: dijit/_FocusMixin
Called when the widget stops being "active" because focus moved to something outside of it, or the user clicked somewhere outside of it, or the widget was hidden.
Examples
Example 1
var btn = new Button();
// when /my/topic is published, this button changes its label to
// be the parameter of the topic.
btn.subscribe("/my/topic", function(v){
this.set("label", v);
});
Next, in your event handler, you are trying to change the text to lowerCase and this can be done like
makeAllSmall : function(){
var currVal=this.get("value");
currVal = currVal.toLowerCase();
/**Some Other business logic on currVal **/
}
Another way of doing this without the event handler is to force the ValidationTextBox to convert everything to lowercase using construction parameters like
<input
id ="NZ2",
data-dojo-attach-point = "NZ2"
data-dojo-attach-type = "ecm.widget.ValidationTextBox"
data-dojo-props='lowercase:true'
data-dojo-attach-event = "onBlurr : makeAllSmall"
/>
Note that I have added data-dojo-props='lowercase:true'
Hope this helps.
You should be able to attach a DOM event to your custom widget by:
Using data attribute data-dojo-attach-event in the markup.
And using _AttachMixin passing your callBack function.
Example:
<div id="somenode"><span data-dojo-attach-point="anattachpoint"
data-dojo-attach-event="click: clicked">Click me</span></div>
var MyDijit = declare([ _WidgetBase, _AttachMixin ], {
// .. declaration goes here ..
clicked: function(e) {
// handle event
}
});
// instantiate the dijit instance, which will attach to the 'somenode' div.
var mydijit = new MyDijit({}, dom.byId('somenode'));
mydijit.startup();
I have looked through all of the similar questions available at the time of this question, and none of the solutions presented worked in the below code. Google was also not helpful except that I did find a few issues with dynamic code where the entire menu was not wrapped, but those issues should be fixed with either the trigger or enhanceWithin methods - which have been tried here.
I am a fairly new with javascript and the jquery library and this is my first app with jquery mobile.
The raw html as generated from the php file:
<div class="cell_container force_org_select">
<label for"force_org[new_555]" class="ui-hidden-accessible">Troop Type</label>
<select name="force_org[new_555]" id="force_org[new_555]" class="roster_cell" data-mini="true">
<option value="hq">HQ</option>
<option value="elite">Elite</option>
<option value="solo">Solitaire</option>
<option value="formation">Std Formation</option>
</select>
The Javascript function that handles the dynamic injection:
$(document).on('click','.add_item', function(event) {
event.preventDefault();
var the_link = $(this).attr('href')
var area = getParameterByName(the_link, 'area');
var type = getParameterByName(the_link, 'type');
var squad_id = getParameterByName(the_link, 'squad_id');
var vehicle = getParameterByName(the_link, 'vehicle');
var divider = getParameterByName(the_link, 'divider');
var preset = $('#preset').val();
$.post(cmd_ajax.ajaxurl,{action: 'cmd_add_item_mobile', type: type, preset: preset, squad_id: squad_id, vehicle: vehicle, divider: divider}, function(data) {
if(type == 'squad' || type == 'divider') {
$('#list').append(data).enhanceWithin();
//$('#list').append(data).trigger("refresh");
//$('#list').append(data).trigger("create");
$('.squad_help_button').tooltipster({
contentCloning: true,
trigger: 'custom',
triggerOpen: {
click: true,
tap: true
},
triggerClose: {
click: true,
tap: true
}
});
}
else {
$('#' + area).append(data).enhanceWithin();
}
//console.log("squad_id:"+this_id);
set_unit_sortable();
});
return false;
});
I also tried adding the .selectmenu("refresh",true) within the function and that seems to do nothing. The custom selects that are not dynamically generated work fine.
If I use the data-native-menu="false" attribute on the generated select menus, the popup does not function and you cannot select anything, if I remove the attribute, the native select works as it should.
I thought about using a selectmenu() refresh at the very end of the function, but I can't seem to catch the element id of the select menu either. My only guess is that it isn't created yet in the DOM when I try to retrieve it.