AngularJS - Fire a function on ng-init=true - javascript

Hi I have the following code:
html:
<div class="portlet-titlebar"
ng-click="toggleCollapsed(portlet, $event)"
ng-class="{current: hover}"
ng-init="hover = false"
ng-mouseenter="hover = hoverIn()"
ng-mouseleave="hover = false">
<span class="arrow">
<svg height="20" viewBox="0 0 32 32" width="20"><path d="M16.7 11.3c-0.4-0.4-1-0.4-1.4 0l-9 9c-0.4 0.4-0.4 1 0 1.4 0.4 0.4 1 0.4 1.4 0L16 13.4l8.3 8.3c0.4 0.4 1 0.4 1.4 0 0.4-0.4 0.4-1 0-1.4L16.7 11.3z" fill="#121313"/></svg>
</span>
<span class="titlebar-text" title="{{portlet.title}}">{{portlet.title}}</span>
</div>
inside the angularJS directive:
scope.hoverIn = function(){
if(event.ctrlKey){
return true;
}
return false;
}
I'm using less for the styling, so inside my less file I have:
.current{
border: 1px solid red;
}
Now what I'm trying to do is: on mouseover + crtl key pressed, I want to change the span class="arrow" icon to another icon and then on click on the icon (while ctrl is still pressed) fire another function. Anybody know what is the best approach to this, as I tried to handle the hover like so, but it didn't work:
document.element.getElementsByClassName('portlet-titlebar').hover(function () {
$(this).toggleClass('current');
});
$(document).keypress(function (e) {
if (e.which == 17) {
$('.current').remove();
}
});
but for some reason it doesn't work..

you have javascript event .onmouseover, i think it will do the job

Related

CSS hover and cursor don't work in shadow DOM

I'm working on a browser addon that inserts a widget into any website as a shadow DOM, but for some reason I'm unable to make the CSS :hover selector and cursor property working.
Here's the snippet of the content script that creates the shadow DOM:
var inpagePopupHTML = "";
var insertStylesHTML = "";
// load the widget HTML from a resource file (works fine)
$.get(browser.runtime.getURL("/ui/mistake-popup.html"), function(data) {
inpagePopupHTML = data;
});
// load the style for the widget from an HTML file that only contains <style>...</style> (works fine)
$.get(browser.runtime.getURL("/css/insert-styles.html"), function(data) {
insertStylesHTML = data;
document.body.innerHTML += data; // the CSS file is inserted here because it also contains styles for the whole page, not just the inserted widget
});
$("body").append('<div class="grammle--shadow" style="all: initial;"></div>'); // "all: initial" prevents the shadow DOM from inheriting styles
var shadow = document.querySelector(".grammle--shadow").attachShadow({ mode: "open" });
shadow.innerHTML += inpagePopupHTML;
shadow.innerHTML += insertStylesHTML; // the same CSS file is also put into the shadow DOM since it contains styles for the inserted widget
Here's the content of mistake-popup.html:
<div class="grammle--popup grammle--popup--minimised">
<div class="grammle--popup-text">
<span class="grammle--popup-text-counter">0</span>
<span class="grammle--popup-text-label">Fehler</span>
</div>
<div class="grammle--popup-icons">
<span class="grammle--popup-icon" part="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-up" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>
</svg>
</span>
<span class="grammle--popup-icon" part="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
<path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"/>
</svg>
</span>
</div>
</div>
Here's insert-styles.html:
<style>
:root {
--grammle-dark-main-colour: #137768;
--grammle-dark-main-colour-hover: #0f6a5d;
}
...
.grammle--popup-icon {
cursor: pointer;
padding: 4px;
background-color: var(--grammle-dark-main-colour);
border-radius: 3px;
}
.grammle--popup-icon:hover {
background-color: var(--grammle-dark-main-colour-hover);
}
...
</style>
Here's a preview of the green widget being correctly inserted and displayed in the right bottom corner on https://keyoxide.org/hkp/pixelcode#dismail.de, just as intended:
As you can see, the “static style” of the widget is correctly applied (so it's not a problem of the CSS not being inserted, for example), but when moving the cursor over either of the icon buttons, neither the darker background colour nor the pointer cursor are applied.
Why is that and how to fix it?
Thanks for your help!
I found a work-around myself: Instead of adding the CSS styles in-line, I added a <head> element to the shadow DOM:
var shadowHead = document.createElement("head");
$(shadowHead).append('<link rel="stylesheet" href="' + browser.runtime.getURL("/css/insert-styles.css") + '" type="text/css" />');
$(shadow).prepend(shadowHead);
I don't know why, but this works now.

How to make cursor pointer while pointer-events is none

I have input type="text" associated with a datalist, and I want to add a fixed arrow (svg) in the input box so that when someone clicks it the datalist opens (as they clicked the box).
The problem is that the arrow I added has its default cursor-events so by default when I click it the datalist doesn't open.
I changed the cursor-events to none, the problem is solved but the cursor now is text, I want it to be pointer whenever mouse is over the arrow and text whenever mouse is over the box.
I tried the solution here: https://stackoverflow.com/a/25654479/7867670 but it didn't work for me
I tried to add an onclick event listener to the arrow and to trigger input click whenever the arrow is clicked, didn't work too.
input::-webkit-calendar-picker-indicator {
display: none !important;
}
.wrapper{
position: relative;
display: inline;
left: -25px;
cursor: pointer;
}
.wrapper svg{
pointer-events: none;
}
<input type="text" list="mylist" name="inp" />
<div class="wrapper" onclick="getElementsByName('inp')[0].click();">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" d="M16.293 9.293L12 13.586L7.707 9.293l-1.414 1.414L12 16.414l5.707-5.707z" />
</svg>
</div>
<datalist id="mylist">
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
</datalist>
As far as I know, this is not possible without JavaScript.
The arrow can only change the cursor if it has pointer-events that is not none, but then the input won't get the click.
input can't have children so that is also not an option.
All of the search results indicate that the datalist can't be opened (reliably?) with JavaScript or html only solutions.
The only thing that comes to my mind is to change the cursor programmatically:
function isEventInElement(event, element) {
var rect = element.getBoundingClientRect();
var x = event.clientX;
if (x < rect.left || x >= rect.right) return false;
var y = event.clientY;
if (y < rect.top || y >= rect.bottom) return false;
return true;
}
const inputElement = document.querySelector('[name="inp"]')
const inputElementArrow = document.querySelector('.wrapper')
inputElement.addEventListener('mousemove', (evt) => {
if (isEventInElement(evt, inputElementArrow)) {
inputElement.style.cursor = 'pointer'
} else {
inputElement.style.cursor = null;
}
})
input::-webkit-calendar-picker-indicator {
display: none !important;
}
.wrapper {
position: relative;
display: inline;
left: -25px;
pointer-events: none;
}
.wrapper svg {}
<input type="text" list="mylist" name="inp" />
<div class="wrapper" onclick="getElementsByName('inp')[0].click();">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" d="M16.293 9.293L12 13.586L7.707 9.293l-1.414 1.414L12 16.414l5.707-5.707z" />
</svg>
</div>
<datalist id="mylist">
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
</datalist>
Code form other answers:
isEventInElement: Detect if a mouse event occurred inside an element's client area
You would want to set the input's cursor via css. Preferably add a css class to the input cursor-pointer and create some css for that selector.
.cursor-pointer {
cursor: pointer !important;
}
If I'm not mistaken, it sounds like you're not expecting the user to type in the input field but rather click it like a dropdown. If that's the case I would recommend using a button to trigger the list, if possible.

How do I trigger an animation in A-frame 1.0.4?

After reading through the a-frame animation documentation, I was working around with some code in JSFiddle to get an idea of how it actually works. Seemed pretty simple... Until I tried to apply it to my own project. What was working in JSFiddle, doesn't work in my project. The console returns the error: "document.querySelector(...).emit is not a function". In the fiddle I was working on, a-frame was set to its 0.3.0 version. I need to use the most recent version - 1.0.4. Is there an alternative to "emit"?
Here's the JSFiddle, and a code snippet. Both are working with the 0.3.0 version of A-Frame.If you change the script src from "https://aframe.io/releases/0.3.0/aframe.min.js" to "https://aframe.io/releases/1.0.4/aframe.min.js" though, you will observe that it no longer works.
https://jsfiddle.net/6y5qbr4z/
function lookAway() {
document.getElementById("myCam").innerHTML = '<a-animation id="away" begin="move-away" attribute="rotation" dur="2000" to="20 20 0"></a-animation>';
setTimeout(function(){document.querySelector('#away').emit('move-away');}, 1)
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="lookAway();">Look Away</button>
<div class="sceneWrapper">
<a-scene embedded>
<a-camera id="myCam" wasd-controls-enabled="false" look-controls="reverseMouseDrag:true">
</a-camera>
<a-sky src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/1920px-Equirectangular_projection_SW.jpg"></a-sky>
<a-sphere id="ball" material="color: red" position="0 1.5 -5"></a-sphere>
</a-scene>
</div>
I tried running your examples both the JS fiddle and the code snipet provided. on my local machine i.e through create a html page, add script, css and test,both are working without any errors.
I got this error when I block the aframe.io libraty from loading in the network tab.Can you please confirm that this is not the case.
Are you triggering the lookAway() function before aframe.io library has loaded ?
Is your library loading properly ?
If the above reasons are not one of the reasons for your error.please can you provide more info.
I also checked the checked the documentation for an alernative of .emit function
emit : emits a custom DOM event on the entity. For example, we can emit an event to trigger an animation
So we can trigger custom DOM evennts using javascript as well. please refer snippet for example.
function moveAway() {
document.getElementById("myCam").innerHTML = '<a-animation id="away" begin="move-away" attribute="rotation" dur="2000" to="20 20 0"></a-animation>';
// setTimeout(function(){
// document.querySelector('#away').emit('move-away');},
// 1)
setTimeout(() => document.querySelector('#away').dispatchEvent(new CustomEvent("move-away", {
bubbles: true
})));
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="moveAway();">Move Away</button>
<div class="sceneWrapper">
<a-scene embedded>
<a-camera id="myCam" wasd-controls-enabled="false" look-controls="reverseMouseDrag:true">
</a-camera>
<a-sky src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/1920px-Equirectangular_projection_SW.jpg"></a-sky>
<a-sphere id="ball" material="color: red" position="0 1.5 -5"></a-sphere>
</a-scene>
</div>
I get your point now, sorry I didnt notice the version above
The <a-animation> element was deprecated in a-frame 0.9.0 in favor of the animation component.
It should look a little bit like this:
<a-camera id="myCam" wasd-controls-enabled="false" rotation="0 0 0" look-controls="reverseMouseDrag:true" animation="property: rotation; to: 0 360 0; loop: false; dur: 10000; startEvents: move-away">
please refer example implementation example
function moveAway() {
// document.getElementById("myCam").setAttribute("animation", "property: rotation; to: 0 360 0; loop: false; dur: 10000; startEvents: move-away")
// document.getElementById("myCam").innerHTML = '<a-animation id="away" begin="move-away" attribute="rotation" dur="2000" to="20 20 0"></a-animation>';
setTimeout(function(){
document.querySelector('#myCam').emit('move-away');},
1)
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="moveAway();">Move Away</button>
<div class="sceneWrapper">
<a-scene embedded>
<a-camera id="myCam" wasd-controls-enabled="false" rotation="0 0 0" look-controls="reverseMouseDrag:true" animation="property: rotation; to: 0 360 0; loop: false; dur: 10000; startEvents: move-away">
</a-camera>
<a-sky src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/1920px-Equirectangular_projection_SW.jpg"></a-sky>
<a-sphere id="ball" material="color: red" position="0 1.5 -5"></a-sphere>
</a-scene>
</div>
Please do let me know if anything else is needed.
Thank you

jQuery - Get length and trigger click in increments based on length

Sorry if I'm completely missing with the title, I'm not entirely sure how to word what it is I'm trying to achieve. Any help would be great!!
Over the past few months in my free time I've been setting myself tasks to help myself understand and learn javascript / jQuery. So far all is going well but I've hit a bit of a bump in the road!
Essentially what I've created is a pretty simple set of tabbed content with a changing banner. When you click a tab, the relevant banner fades in and the previous banner fades out
Here's a fiddle: http://jsfiddle.net/unn9s4yf/
So what I'd like to do and where I'm kind of stuck is I'd like the banners to automatically "rotate", by fading in and out in the tabbed order every 10 seconds or so.
So kind of like a trigger click, but I feel as if that'd be the wrong way to go?
$('.thumb' + idAttr).trigger("click");
With a timeout attached? I'm not sure? I'm also not sure how to increment it each time so if this was the chosen method, how would it start at thumb 1, then click 2, 3, 4 & so on?
I've got the number of thumbs inside the div using
var thumbCount = $('#thumbs a').length;
Which returns 15 which is correct. So I guess it'd be something like when idAttr = .length start over from 1 again?
I'd also like to be able to pause the "auto click" function when I hover overthe main banner or thumbnails, I don't know if this is achievable though?
I know I'm asking a lot here.... At least I think I am. But any help or guidance on any part of this would be massively appreciated.
Thank you for your time!
I forked your jsfiddle and tried to do what you asked.
http://jsfiddle.net/OxyDesign/2g5Lav12/
It changes every 3 seconds, comes back to first thumb after the last thumb, stops on mouseenter & plays on mouseleave (on thumbs & banners), and stops on click & plays on second click on the same thumb.
HTML
<div id="container">
<div id="thumbs">
<a class="thumb active"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
<a class="thumb"></a>
</div>
<div id="banner">
<div class="banner active"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
<div class="banner"></div>
</div>
</div>
CSS
#container {width: 960px; margin: 0 auto;}
div,
a {float: left; display: block;}
#thumbs {width: 600px;}
.thumb {width: 110px; height: 156px; margin: 0 10px 10px 0; cursor: pointer;}
.thumb:hover,
.thumb.active,
.thumb.clicked {opacity: 0.5;}
.thumb:nth-child(even) {background: #ccee44;}
.thumb:nth-child(odd) {background: #ff33dd;}
#banner {width: 360px;}
.banner {width: 360px; height: 488px; position: absolute; display: none;}
.banner.active {display: block;}
.banner:nth-child(even) {background: #ccee44;}
.banner:nth-child(odd) {background: #ff33dd;}
JS
$(document).ready(function() {
var thumbs = $('.thumb'),
firstThumb = thumbs.eq(0),
banners = $('.banner'),
all = thumbs.add(banners),
duration = 3000,
rotating = false,
intervalRotate;
function setAutoRotate(){
intervalRotate = setInterval(autoRotate,duration);
rotating = true;
}
function stopAutoRotate(){
clearInterval(intervalRotate);
rotating = false;
}
function autoRotate(){
var nextThumb = thumbs.filter('.active').next();
if(!nextThumb.length) nextThumb = firstThumb;
rotate(nextThumb);
}
function rotate(activeThumb){
thumbs.removeClass('active');
activeThumb.addClass('active');
banners.removeClass('active').eq(thumbs.index(activeThumb)).addClass('active');
}
thumbs.on('click',function(e){
e.preventDefault();
var thumb = $(this);
if(thumb.hasClass('clicked')){
thumb.removeClass('clicked');
}else{
stopAutoRotate();
thumbs.removeClass('clicked');
thumb.addClass('clicked');
rotate(thumb);
}
});
all.on('mouseenter',function(){
if(rotating) stopAutoRotate();
});
all.on('mouseleave',function(){
if(!thumbs.filter('.clicked').length) setAutoRotate();
});
setAutoRotate();
});
Is it the behaviour you wanted ?
Triggering a click with a timeout should work fine. You could even do it recursively if you never want it to end. Also, you can set a variable to decide when to stop the rotation
$(function() {
$('.thumb').click(function(event, isAutoClick){
//Is Not automatic click, set false
if (!isAutoClick) isRotationActive = false;
//Other Click Code
});
//If hover over banner, stop rotation
$("#banner").on("mouseover", function() {
isRotationActive = false;
});
rotate($(".thumb"), 0);
});
var isRotationActive = true;
function rotate($clickables, currentIndex) {
//Make sure currentIndex is valid
currentIndex = currentIndex % $clickables.length;
//Trigger current click
$clickables.eq(currentIndex).trigger("click", [true]); //Passes [true] for isAutoClick
//Call again in 1 second with the next index
setTimeout(function() {
isRotationActive && rotate($clickables, currentIndex + 1)
}, 1000);
}
Updated Fiddle here: http://jsfiddle.net/unn9s4yf/3/
An Additional Solution:
var thumbs = $('.thumb');
var currentThumb = 0;
var changingStopped = false;
var changeBanner = function() {
console.log(thumbs.eq(currentThumb));
thumbs.eq(currentThumb).click();
currentThumb >= thumbCount - 1 ? currentThumb = 0 : currentThumb++;
setTimeout(function() {
checkIfChange();
}, 1000);
}
// triggers 'changeBanner()' if the user isn't currently stopping it.
var checkIfChange = function() {
if (!changingStopped)
{
changeBanner();
}
}
// makes the rotation stop
$('.thumb').mouseenter(function() {
changingStopped = true;
$(this).trigger('click'); // Assuming you want the hovered-over thumb to be displayed in the banner.
currentThumb = $(this).index() + 1; // Additional Option to make the rotation begin again from the current thumb.
});
// makes the rotation start again
$('.thumb').mouseleave(function() {
changingStopped = false;
checkIfChange();
});
checkIfChange();
See JSFiddle. Cheers!

Best practice for a button with image and text in mobile website

Refer to the screenshot below, I have created a div to wrap another two div of image and text, then I use CSS position: absolute to make these div merge together.
However, I found that the button is not sensitive while testing on mobile devices, sometime I need to touch the button few time to take effect.
So, is there something wrong for my code and what is the best practice to create a button with image and text?
Thanks
<div class="r">
<div class="a">
<div class="i"><img src="store_btn_on.png" /></div>
<div class="t">Shatin</div>
</div>
<div class="b">
<div class="i"><img src="store_btn_off.png" /></div>
<div class="t">Causeway Bay</div>
</div>
<div class="c">
<div class="i"><img src="store_btn_off.png" /></div>
<div class="t">Kowloon Bay</div>
</div>
</div>
Update for the part of javascript
addButtonListener($("#store > .r > .a"), function(event, target){
$("#some_content").css("display", "none");
$("#other_content").css("display", "block");
$(".r > .b > .a > img").attr("src" , "store_btn_on.png");
$(".r > .b > .b > img, .r > .b > .c > img").attr("src" , "store_btn_off.png");
});
function addButtonListener(targets, job){
if ("ontouchstart" in document.documentElement){
targets.each(function(){
$(this)[0].addEventListener('touchstart', function(event){
event.preventDefault();
$(this).attr({ "x": event.targetTouches[0].clientX, "diffX": 0, "y": event.targetTouches[0].clientY, "diffY": 0 });
$(this).addClass("on");
}, false);
$(this)[0].addEventListener('touchmove', function(event){
$(this).attr({
"diffX": Math.abs(event.targetTouches[0].clientX - $(this).attr("x")),
"diffY": Math.abs(event.targetTouches[0].clientY - $(this).attr("y"))
});
}, false);
$(this)[0].addEventListener("touchend", function(event){
$(this).removeClass("on");
if ($(this).attr("diffX") < 5 && $(this).attr("diffY") < 5){ $(job(event, $(this))); }
}, false);
});
}
else {
targets.each(function(){
$(this).mousedown(function(event){ event.preventDefault(); $(this).addClass("on"); });
$(this).mouseup(function(event){ event.preventDefault(); if ($(this).hasClass("on")){ $(job(event, $(this))); } $(this).removeClass("on"); });
$(this).hover(function(event){ $(this).removeClass("on"); });
});
}
}
I am not sure about the sensitivity of your button on mobile devices (you haven't shown any of your code for handling click events), but I think it is better to write your HTML like this:
<div class="r">
<div class="button on">
<span>Shatin</span>
</div>
<div class="button">
<span>Bay</span>
</div>
<div class="button">
<span>Bay</span>
</div>
</div>
Then use CSS in your stylesheet:
.button {
background: url(http://domain.com/images/store_btn_off.png) no-repeat 0 0;
/* Additional button styles */
}
.button.on {
background: url(http://domain.com/images/store_btn_on.png) no-repeat 0 0;
}
.button span {
color: #FFF;
margin: auto;
}
This makes it easy to dynamically turn a button on or off just by adding or removing the on class.
Although not necessary, you may also be interested in looking at CSS3 gradients to create simple gradient background images like that, and then degrade nicely to an image in browsers without any gradient support.
The class names "r" and "b" are not very descriptive. Unless some HTML/CSS minifier put those there and you have proper names in your development code, I would consider giving your classes more descriptive names as well.

Categories

Resources