Select2 - Show/Hide div based on selection - jquery-select2

I am trying to have a div show if an option is selected using the Select2 plug in.
I tried using the following code but it does not work:
$(document).ready(function() {
var h = $(".shipment-details--other-description");
$("#shipment-details-select-pacakage-types").change(function() {
if (this.checked && this.value == "Other") {
h.show();
} else {
h.hide();
}
}).change()
});
The div is being hid but not being shown if the Other option is selected.
Is there a different way to do this with Select2?
Edit: Forgot to mention that this a multiple select field. Also, adjusted the code and took out the this.checked as that was for a check field.

try to create a new css class, is-hidden{ display:none;}
$(document).ready(function() {
var h = $(".shipment-details--other-description");
$("#shipment-details-select-pacakage-types").change(function() {
if (this.checked && this.value == "Other") {
h.addClass('is-hidden');
} else {
h.removeClass('is-hidden');
}
}).change()
});

Related

Text object styling not set correctly when loading canvas from serialized data

I have created a custom label maker using the Konvajs library. I provided the user with a label library to choose from as a starting point or the option to create a label from scratch. If the user selects from the label library I load the label via Json and I provide the user with the ability to edit any text elements with external controls. The user has the ability to set the following properties:
fontFamily
fontSize
fontStyle
fontVariant
lineHeight
fill
align
When the user clicks on a text object on the canvas the external controls are set with the text objects properties allowing the user to modify any of the properties listed above.
The issue I'm having is when the label is loaded the text format is the default until the user clicks on the text to edit, then all the pre-set properties are applied. I need the pre-set properties to display when first loaded.
Here is my function for loading the Json:
function loadCanvasFromJson(json) {
//Remove the disable class from action buttons...
$('.dropdown-action-btn').addClass('disabled');
stage = Konva.Node.create(json, 'labelcontainer');
stage.find('Image').forEach((imageNode) => {
const src = imageNode.getAttr('src');
const image = new Image();
image.onload = () => {
imageNode.image(image);
imageNode.getLayer().batchDraw();
}
image.src = src;
});
stage.find('Text').forEach((textNode) => {
textNode.on("mouseover", function(e){
document.body.style.cursor = 'pointer';
});
textNode.on('mouseout', function() {
document.body.style.cursor = 'default';
});
textNode.on('click', function(evt) {
var text = evt.target;
$('#add-label-text').addClass('hidden');
$('#update-label-text').removeClass('hidden');
$('#delete-label-text').removeClass('hidden');
setTextClickValues(text);
});
});
}
Here is the function for setting the external editor controls when a text object is clicked:
function setTextClickValues(text) {
var textObj = text.getAttrs();
console.log(textObj);
for (attr in textObj) {
if (attr == 'align') {
$('#text-align').val(text.getAttr(attr));
if (text.getAttr(attr) == 'center')
$('.text-format-text-align-center').addClass('active');
if (text.getAttr(attr) == 'left')
$('.text-format-text-align-left').addClass('active');
if (text.getAttr(attr) == 'right')
$('.text-format-text-align-right').addClass('active');
}
if (attr == 'id') $('#text-group').val(text.getAttr(attr).replace('text',''));
if (attr == 'text') $('#label-text').val(text.getAttr(attr));
if (attr == 'lineHeight') {
$('#text-lineheight').val(text.getAttr(attr));
$('#lineHeight').val(text.getAttr(attr));
}
if (attr == 'fontSize') {
$('#text-size').val(text.getAttr(attr));
$('#fontSize').val(text.getAttr(attr));
}
if (attr == 'fill') {
$('#text-fill').val(text.getAttr(attr));
$('.colorPickSelector.fill').css('background-color', text.getAttr(attr));
$('.colorPickSelector.fill').css('color', text.getAttr(attr));
if (text.getAttr(attr) == '#ffffff') {
$('.colorPickSelector.fill').css('border','1px solid rgb(221, 221, 221)');
}
}
if (attr == 'fontFamily') {
$('.text-format-dropdown-current').val(text.getAttr(attr));
$('#text-font').val(text.getAttr(attr));
}
if (attr == 'fontVariant') {
$('#text-fontVariant').val(text.getAttr(attr));
if (text.getAttr(attr) == 'small-caps')
$('.text-format-text-variant').addClass('active');
}
if (attr == 'textDecoration') {
$('#text-textDecoration').val(text.getAttr(attr));
if (text.getAttr(attr) == 'underline')
$('.text-format-text-underline').addClass('active');
}
if (attr == 'fontStyle') {
$('#text-fontStyle').val(text.getAttr(attr));
if (text.getAttr(attr).indexOf('bold') > -1) {
$('.text-format-text-bold').addClass('active');
}
if (text.getAttr(attr).indexOf('italic') > -1) {
$('.text-format-text-italic').addClass('active');
}
}
}
}
I guess on your first stage load, the font is not loaded yet. So you need to wait until the font is loaded and then redraw a layer.
For the best solution you should use something like font observer:
How to be notified once a web font has loaded
Or you can simply redraw layer on timeout (but this solution is not perfect).

Hide selected items in select2

I'm trying to use select2 jQuery plugin to enhance a select element in HTML app. The select allow to choose multiple items.
I'll like to remove the items that are currently selected from the dropdown. I didn't find explicit solution in the docs.
The current solution I've found was to use templateResult option and have the template function return null if the item is selected. This cause Results.prototype.template function to set container.style.display = 'none' but this has the side-effect of causing the keyboard to still select those items even though they are not visible.
Just apply this CSS.
.select2-results__option[aria-selected=true] { display: none;}
Small Update for recent versions :
.select2-results__option--selected { display: none;}
Source
Check out the answer provided here, provided by Hakam Fostok.
I've reproduced his answer below here for completeness:
my solution was modified the select2.js (the core, version 4.0.3) in the line #3158. Add the following verification :
if ($option[0].selected == true) {
return;
}
With this verification, we can exclude from the dropdown list, the selected ones. And if you write the name of a selected option, appear the text of option "noResult" .
Here the complete code:
SelectAdapter.prototype.query = function (params, callback) {
var data = [];
var self = this;`
var $options = this.$element.children();`
$options.each(function () {
var $option = $(this);
if (!$option.is('option') && !$option.is('optgroup') ) {
return;
}
if ($option[0].selected == true) {
return;
}
var option = self.item($option);
var matches = self.matches(params, option);
if (matches !== null) {
data.push(matches);
}
});
callback({
results: data
});
};
For my purposes, I was using the select2.js file, so I made the change at line 3195.
For versions 4 and 4.1
.select2-container--default .select2-results__option[aria-selected=true] {
display: none !important;
}
Works fine!
In addition to #Satheez answer, this script will let you maintain the placeholder after hiding all the selected items.
$('.selector').select2().on("change", function (e) {
$('.select2-search__field').attr('placeholder', 'Here is your placeholder');
});

photoswipe returning to initial hash of current page instead of last scroll position

On IOS, when I close photoswipe to return to the page, it wont return to the scroll position I was at when I clicked the thumbnail.
Instead the page scrolls back to the # which was specified when I initially called the page.
For example if photoswipe is on www.somepage.html, and I navigate to the page using:
www.somepage.html#footer
and then scroll up and click a thumnail in #middle of page, on closing photoswipe, the page scrolls back down to the footer.
I've tried disabling history in the photswipe options, and i've also tried clearing the hash data from the url using:
//clear hash
//$(document).ready(function (e) {
// window.location.hash = '';
// window.history.pushState("", document.title, window.location.pathname);
//
//});
But none of it seems to work. If I navigate to the page without the # in the page, everthing is fine.
I'm guessing I may have to pass a variable in the url instead of the # and scroll to the div in question via javascript?
I already have the javascript in place to scroll, but I'm not sure how to read the variable from the url and then use it's value in Javascript.
If this is likely to be the best fix for the issue, could anyone give an example of the javascript code needed?
Here's my current scroll code:
$(function () {
$('a[href*=#]:not([href=#],[data-toggle],[data-target],[data-slide])').click(function () {
if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') || location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
If anyone else has the same issue, I've managed to fix this by passing the div id to the page in the query string rather than using a #.
Here's the code:
$(window).ready(function () {
if (document.location.search.length) {
target = getUrlVars()["id"];
scrollToID('#' + target, 750);
} else {
return;
}
//target = $url().param('id');
//if (target == '') return;
});
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
// scroll function
function scrollToID(id, speed){
var offSet = 100;
var targetOffset = $(id).offset().top - offSet;
var mainNav = $('#main-nav');
$('html,body').animate({scrollTop:targetOffset}, speed);
if (mainNav.hasClass("open")) {
mainNav.css("height", "1px").removeClass("in").addClass("collapse");
mainNav.removeClass("open");
}
}
if (typeof console === "undefined") {
console = {
log: function() { }
};
}

Lightbox2 Swipe gesture for touchscreens

To my great surprise Lightbox2(http://lokeshdhakar.com/projects/lightbox2/) does not support swipe gestures out of the box...
I was not able to find any add on in order to support this behavior. Anyone has any suggestions a side from changing the entire plugin? :)
To summary, you must hide the navigation buttons and implement swiping, moving and sliding effect on the image.
You will need :
jquery.event.move
jquery.event.swipe
jquery ui slide effect, you can package it in the jquery ui download builder
maybe there's a simplest way to get/implement all of these 3 small dependencies... but that way works for me.
in the lightbox script, add a new LightboxOptions enableSwipeOnTouchDevices and set it to true :
this.enableSwipeOnTouchDevices = true;
add the following blocks after the this.$lightbox.find('.lb-next').on('click'... block to create the swiping events:
this.$lightbox.find('.lb-image').on("swiperight",function() {
$('.lb-image').effect("slide", { "direction" : "right", "mode" : "hide"} ,function(){
if (self.currentImageIndex === 0) {
self.changeImage(self.album.length - 1);
} else {
self.changeImage(self.currentImageIndex - 1);
}
})
});
this.$lightbox.find('.lb-image').on("swipeleft",function() {
$('.lb-image').effect("slide", { "direction" : "left", "mode" : "hide"} ,function(){
if (self.currentImageIndex === self.album.length - 1) {
self.changeImage(0);
} else {
self.changeImage(self.currentImageIndex + 1);
}
})
});
and rewrite the updateNav function like this to hide the navigation buttons:
Lightbox.prototype.updateNav = function() {
// Check to see if the browser supports touch events. If so, we take the conservative approach
// and assume that mouse hover events are not supported and always show prev/next navigation
// arrows in image sets.
var alwaysShowNav = false;
var enableSwipe = false;
try {
document.createEvent("TouchEvent");
alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices)? true: false;
enableSwipe = (this.options.enableSwipeOnTouchDevices)? true: false;
} catch (e) {}
//if swiping is enable, hide the two navigation buttons
if (! enableSwipe) {
this.$lightbox.find('.lb-nav').show();
if (this.album.length > 1) {
if (this.options.wrapAround) {
if (alwaysShowNav) {
this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
}
this.$lightbox.find('.lb-prev, .lb-next').show();
} else {
if (this.currentImageIndex > 0) {
this.$lightbox.find('.lb-prev').show();
if (alwaysShowNav) {
this.$lightbox.find('.lb-prev').css('opacity', '1');
}
}
if (this.currentImageIndex < this.album.length - 1) {
this.$lightbox.find('.lb-next').show();
if (alwaysShowNav) {
this.$lightbox.find('.lb-next').css('opacity', '1');
}
}
}
}
}
};
I've used jquery mobile to detect swipeleft and swiperight. Then bind them to click .lb-next and .lb-prev. It's working now.
Here is my codepen.
PEC's solution worked for me with one modification on a Jekyll site.
Instead of:
this.enableSwipeOnTouchDevices = true;
We added this to /_includes/scripts.html after the dependencies and lightbox.js:
<script>
lightbox.option({
'enableSwipeOnTouchDevices': true,
})
</script>
The PEC solution is good, but it doesn't work anymore with the current version of lightbox (2.11.2). The effect() method doesn't exists anymore.
So the swiping methods should be updated:
this.$lightbox.find('.lb-image').on("swiperight",function() {
if (self.currentImageIndex === 0) {
self.changeImage(self.album.length - 1);
} else {
self.changeImage(self.currentImageIndex - 1);
}
return false;
});
this.$lightbox.find('.lb-image').on("swipeleft",function() {
if (self.currentImageIndex === self.album.length - 1) {
self.changeImage(0);
} else {
self.changeImage(self.currentImageIndex + 1);
}
return false;
});
Less fancy, but shorter and works.
In short: 'catch' swipe gesture and then trigger 'click' on next/prev button based on swipe direction.
let touchstartX = 0;
let touchendX = 0;
function handleGesture() {
if (touchendX < touchstartX) $(".lb-prev").trigger("click");
if (touchendX > touchstartX) $(".lb-next").trigger("click");
}
$(document).on("touchstart", ".lb-nav", e => {
touchstartX = e.changedTouches[0].screenX;
});
$(document).on("touchend", ".lb-nav", e => {
touchendX = e.changedTouches[0].screenX;
handleGesture();
});

jquery mobile plugin creation

I am trying to create a plugin for JQuery Mobile. Does anyone have a template or examples to help? Currently, I have the following defined in myplugin.js
(function ($) {
$.fn.myPlugin = function (options) {
var defaults = { e: 0 },
settings = $.extend({}, defaults, options);
var h= $.myPlugin.getHtml(options.e);
alert("here 1");
if ((h != null) && (h != undefined) && (h.length > 0)) {
alert("here 2");
this.html(h);
}
};
$.myPlugin = {
getHtml: function (e) {
var s = "";
return s;
}
};
})(jQuery);
I am trying to initialize an instance of this plugin like such:
$("#pluginInstance", "#myPage").myPlugin({ e: 0 });
Oddly, neither alert dialog appears. There aren't any errors in the console either. What am I doing wrong?
How about this or this?
If you look how JQM is designed, the syntax is pretty similar. I'm also sticking with it, when working on plugins I'm doing.

Resources