Trying to reproduce something similar to Openlayers with sidebar where once the sidebar is expanded the .ol-zoom margin-left is modified to change its position but I can't use jquery in my project, so looks for Vanilla JS or Angular based solution.
I saw that its quiet easy to change position of the openlayers Zoom buttons as answered here but I would like to change the position on some event trigger like a (sidebar-toggle button) button click.
Thanks
In JS you can dynamically add css to the application, for example
var css =
'.menuSeparator {' +
' border-bottom: solid 1px black;' +
'}';
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
head.appendChild(style);
Here is my solution
const olZoom = document.getElementsByClassName("ol-zoom");
const sideBarElements = document.getElementsByClassName("sidebar-left");
if(!this.sidebarVisibility) {
(olZoom[0] as HTMLElement).style.marginLeft = "0px";
(olZoom[0] as HTMLElement).style.marginTop = "60px";
} else {
setTimeout(() => {
(olZoom[0] as HTMLElement).style.marginLeft = ((sideBarElements[0] as HTMLElement).offsetWidth - 10) + 'px';
(olZoom[0] as HTMLElement).style.marginTop = "0px";
}, 50);
}
major issue what I was facing was that I wasn't casting Element to HTMLElement in typescript as explained here which was blocking me to apply my margin style
Related
I wonder how can I use css/javascript to adjust the blinking cursor inside the search box with CSS?
Is it possible to replace default blinkig caret to horizontal blinking icon
I don't think it is so hard. I made a quick example, which works in most modern browsers except Safari.
It draws the caret on a canvas, and sets it as a background of the input, on a position calculated from the browsers caret position.
It checks if the browser supports the caret-color css property, and if it doesn't it doesn't do anything, because both the system caret, and our caret will be visible in the same time. From the browsers I tested, only Safari doesn't support it.
$("input").on('change blur mouseup focus keydown keyup', function(evt) {
var $el = $(evt.target);
//check if the carret can be hidden
//AFAIK from the modern mainstream browsers
//only Safari doesn't support caret-color
if (!$el.css("caret-color")) return;
var caretIndex = $el[0].selectionStart;
var textBeforeCarret = $el.val().substring(0, caretIndex);
var bgr = getBackgroundStyle($el, textBeforeCarret);
$el.css("background", bgr);
clearInterval(window.blinkInterval);
//just an examplethis should be in a module scope, not on window level
window.blinkInterval = setInterval(blink, 600);
})
function blink() {
$("input").each((index, el) => {
var $el = $(el);
if ($el.css("background-blend-mode") != "normal") {
$el.css("background-blend-mode", "normal");
} else {
$el.css("background-blend-mode", "color-burn");
}
});
}
function getBackgroundStyle($el, text) {
var fontSize = $el.css("font-size");
var fontFamily = $el.css("font-family");
var font = fontSize + " " + fontFamily;
var canvas = $el.data("carretCanvas");
//cache the canvas for performance reasons
//it is a good idea to invalidate if the input size changes because of the browser text resize/zoom)
if (canvas == null) {
canvas = document.createElement("canvas");
$el.data("carretCanvas", canvas);
var ctx = canvas.getContext("2d");
ctx.font = font;
ctx.strokeStyle = $el.css("color");
ctx.lineWidth = Math.ceil(parseInt(fontSize) / 5);
ctx.beginPath();
ctx.moveTo(0, 0);
//aproximate width of the caret
ctx.lineTo(parseInt(fontSize) / 2, 0);
ctx.stroke();
}
var offsetLeft = canvas.getContext("2d").measureText(text).width + parseInt($el.css("padding-left"));
return "#fff url(" + canvas.toDataURL() + ") no-repeat " +
(offsetLeft - $el.scrollLeft()) + "px " +
($el.height() + parseInt($el.css("padding-top"))) + "px";
}
input {
caret-color: transparent;
padding: 3px;
font-size: 15px;
color: #2795EE;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
If there is interest, I can clean it a bit and wrap it in a jQuery plugin.
Edit: forgot about the blinking, so I added it. A better way will be to add it as css animation, in this case the caret should be in a separate html element positioned over the input.
Changing the color of the caret is supported by the latest standards. But not changing its width is not, which I think is a shame because it is a question of accessibility for vision-impaired people.
One approach for implementing such a change yourself is first trying to figure out what is the position the caret is blinking at, then overlaying it with an element that looks like the caret but is perhaps wider etc.
Here's an article on how to go about doing such a thing. It's a good article but the end-solution is kind of complicated as a whole. But see if it solves your problem:
https://medium.com/#jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
Here is perhaps a simpler explanation for how to find the care x-y position:
How do I get the (x, y) pixel coordinates of the caret in text boxes?
note: I do not have access to the HTML or javascript code
I am using the excellent Chrome plugin, Web Override, to improve usability on a vendor site my company uses. I am only looking for CSS solutions (or possibly js/jq scripts I can sideload).
I'm trying to set table rows to highlight on hover, which is easy enough:
#task-list-main-table tr:hover {
background-color: lightyellow;
}
The problem is that there is a little button that appears on each row when you hover over it. This means if I hover over the button, the corresponding row is not highlighted.
Good:
Bad:
I know I could use pointer-events:none but then I can no longer click on the button, which I need to be able to do.
So, is there any way in CSS to "pass through" hover events without affecting click events?
This is a pretty convoluted method, but if you have the ability to inject javascript, this function will check if your mouse is overlapping whatever element you supply as the selector.
https://jsfiddle.net/tr_santi/aegybp6n/8/
//Change this value to desired element
var hoverElement = "td";
//Change this value to the class you'd like to add when hovering
var addClass = "hover";
function getOffset( el ) {
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
function overlapListener(element, x, y, classToAdd) {
var eTop = getOffset(element).top;
var eLeft = getOffset(element).left;
var eBottom = eTop + element.clientHeight;
var eRight = eLeft + element.clientWidth;
if (x <= eRight && x >= eLeft && y <= eBottom && y >= eTop) {
if (!hasClass(element, classToAdd)) {
element.className = classToAdd;
}
} else {
if (hasClass(element, classToAdd)) {
element.className = "";
}
}
}
var elementList = document.querySelectorAll(hoverElement);
document.onmousemove=function(e){
[].forEach.call(elementList, function(b) {
overlapListener(b, e.clientX, e.clientY, addClass)
});
};
I'm sure there are some JS gurus around here that could write you something a bit less obfuscated, however I found this to be a good practice exercise for myself. I chose to write it in vanilla JS as I'm unsure of what your limitations are, although JQuery could substantially reduce the amount of needed code.
Here is my code, where I'm trying to detect the element, which a jQuery UI draggable is hovering over. I need to get the element's object and attributes, such as class names (in this case .sortable-grid,.sortable-table,.sortable-row,.sortable-cell).
The answers found here only show how to get the draggable item itself (ui.helper or event.target), but not the element it is hovering above.
The best way to answer would be using the prepared JSFiddle, since my code uses an iframe, which would not work if the full code is posted here:
JSFiddle
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0-beta.1/jquery-ui.js"></script>
<div style="background-color:grey;display:inline;cursor:move" id="draggable">DRAG ME</div>
<iframe src="https://fiddle.jshell.net/piglin/UAcC7/1869/show/" id="frame" style="width:100%;overflow:visible" seamless="seamless" scrolling="no"></iframe>
JS:
$("#draggable").draggable({
drag: function(event, ui) {
//Some code here
}
}
It was possible by modifying the function from another answer to fit this purpose. After adapting it to use the contentWindow of the iframe and adding offset calculation it works now.
Solution
function allElementsFromPointIframe(x, y, offsetX, offsetY) {
var element, elements = [];
var old_visibility = [];
while (true) {
element = document.getElementById('frame').contentWindow.document.elementFromPoint(x - offsetX, y - offsetY);
if (!element || element === document.getElementById('frame').contentWindow.document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
elements.reverse();
return elements;
}
var selected = $('');
var tmpColor = 'transparent';
$("#draggable").draggable({
drag: function(event, ui) {
var el = $(allElementsFromPointIframe(event.pageX, event.pageY, $(frame).offset().left, $(frame).offset().top));
var div = $(el).filter('ul, li').not($(this));
selected.css({'backgroundColor': tmpColor});
selected = div.last()
tmpColor = selected.css('backgroundColor');
selected.css({'backgroundColor': 'red'});
console.dir(div);
},
iframeFix: true,
iframeOffset: $('#iframe').offset()
});
It's there any way to animate the "ghost image" when dragging the element?
Just like Google Drive, drag the files will trigger cool effect. I tried to add the CSS animation to the ghost-img, like this but it's not work.
go this way https://jsfiddle.net/mdvrkaer/4/ :
You miss the "drag" event. to move the ghost, make him follow the mouse cursor...
$(document).ready(function(){
dragAndDrop();
$('#ghost-img').hide();
});
function dragAndDrop(){
var dragElement = document.getElementById('row-1');
dragElement.addEventListener("dragstart",function(evt) {
$('#ghost-img').show();
//ghost image
var crt = document.getElementById('ghost-img').cloneNode(true);
crt.style.position = "absolute";
crt.style.top = "0px";
crt.style.right = "0px";
crt.style.zIndex = -1;
document.body.appendChild(crt);
evt.dataTransfer.setDragImage (crt, 0, 0);
},false);
dragElement.addEventListener("drag",function(evt) {
$('.ghost').css('top', evt.pageY);
$('.ghost').css('left', evt.pagex);
},false);
dragElement.addEventListener("dragend",function(evt) {
$('.ghost').hide();
},false);
}
I have a select list where the text within the options is too long as is getting cropped. Is it possible to make the text wrap instead so that all of it is visible?
http://jsfiddle.net/W4KG7/
<select>
<option>This is option 1</option>
<option>This is option 2</option>
</select>
select {
width: 92px;
}
select {
width: 92px;
white-space:pre-wrap;
}
This only appears to work in Google Chrome.
https://developer.mozilla.org/en-US/docs/Web/CSS/white-space
It seems there is no way to accomplish this in Firefox without reinventing the wheel.
The solution I have come up with achieves this for other browsers, and uses an ellipsis in Firefox:
select {
max-width: 100%;
white-space: normal;
/* For Firefox: */
text-overflow: ellipsis;
}
Using CSS to do this will only work in Chrome...
You can't do it just by using CSS, but you can use some jQuery for
a "look like" solution.
As you can see it behaves like you wanted - I'm wrapping the select box with a DIV
and adding another one that will overlap the select box - he takes the select box fixed width minus
the button of the select box. Now I'm assigning to this div the same appearance as the select box +
The selected value.
Every time the select box will be changed the new value will be set in the mask we created and
the calculated new height will be set to the select box to.
Here is the jQuery code:
$(function(){
var mYbrowser = detectBrows();
console.log(mYbrowser[0]);
$('select').each(function(index,ele){
//get current style and fixed width:
var renderWidth = $(ele).outerWidth();
var renderWidthFixed = renderWidth;
var borderstyle = $(ele).css("border-bottom-style");
var bordercolor = $(ele).css("border-bottom-color");
var borderwidth = $(ele).css("border-bottom-width");
var font = $(ele).css("font");
var defaultValue = $(ele).val();
if (borderwidth == "0px") { borderwidth = "1px"; /*FF*/ }
$(ele).css({ cursor:"pointer" });
// set by browser (different buttons):
var borderRightParsed = borderwidth +" " + borderstyle + " " + bordercolor;
var topParsed = Math.round(parseInt(borderwidth.replace(/[^0-9\.]+/g,"")));
switch(mYbrowser[0]) {
case "MSIE": renderWidthFixed = renderWidth-28; break;
case "I": renderWidthFixed = renderWidth-28; break;
case "Chrome": renderWidthFixed = renderWidth-30; break;
case "Firefox":
renderWidthFixed = renderWidth-27;
borderRightParsed= "0";
if (index > 0) topParsed++;
break;
}
//wrap + add a overlapping layer that will hide content and calculate the correct height:
$(ele).wrap($('<div />').css({width:renderWidth, margin:0, padding:0, position:"relative"}));
$(ele).after($("<div>" + defaultValue + "</div>")
.css({
minHeight:20,
padding:"5px 0px 5px 8px",
width:renderWidthFixed,
backgroundColor:"white",
whiteSpace:"pre-wrap",
position:"absolute",
borderRight:borderRightParsed,
top:topParsed,
cursor:"default",
left:borderwidth,
font:font
})
);
//set select box new height:
setHeight(ele);
//append change behavior:
$(ele).change(function(){
$(ele).next('div').text($(ele).val());
setHeight(ele);
});
});
function setHeight(ele) {
var newHeight = $(ele).next('div').outerHeight();
$(ele).height(newHeight);
}
function detectBrows(){
var ua= navigator.userAgent, tem,
M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if(/trident/i.test(M[1])){
tem= /\brv[ :]+(\d+)/g.exec(ua) || [];
return 'IE '+(tem[1] || '');
}
if(M[1]=== 'Chrome'){
tem= ua.match(/\bOPR\/(\d+)/)
if(tem!= null) return 'Opera '+tem[1];
}
M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
return M;
}
});
Its simple and not complicated - the problem is that the select box element behave
and look different on each browser.
I added a small quick function to detect which browser is used and fine tuning his
unique values.
This method can be Improved but that's a good starting point.
Shlomo