I have a problem. I wish to flash (or blink) text from yellow to grey, but I would like the yellow text to remain displayed longer than the grey text.
The code that I have works for an equal duration for each color.
function flashtext(ele,col) {
var tmpColCheck = document.getElementById( ele ).style.color;
if (tmpColCheck === 'grey') {
document.getElementById( ele ).style.color = col;
} else {
document.getElementById( ele ).style.color = 'grey';
}
}
setInterval(function() {
flashtext('flashingtext','yellow');
}, 700 ); //set an interval timer up to repeat the function
Any ideas?
Something like this, you mean?
function flashtext(id, col) {
var grey = true,
el = document.getElementById(id);
(function f() {
grey = !grey;
el.style.color = grey ? 'grey' : col;
setTimeout(f, grey ? 500 : 1000);
})();
};
demo at http://jsfiddle.net/alnitak/8LYG2/
This code uses the local variable grey to store the current state, rather than attempt to read it from the element. This is both very efficient, and eliminates the risk that the browser might have converted the .style.color property into another format.
The inner closure is then responsible for toggling the state, changing the element's style, and then recursively queueing itself again with the appropriate timeout.
You can use setTimeout:
function flashtext(ele,col) {
var tmpColCheck = document.getElementById( ele ).style.color,
time;
if (tmpColCheck === 'grey') {
document.getElementById( ele ).style.color = col;
time=1400;
} else {
document.getElementById( ele ).style.color = 'grey';
time=700;
}
setTimeout(function(){flashtext('flashingtext','yellow')},time);
}
flashtext('flashingtext','yellow');
DEMO: http://jsfiddle.net/EfpEP/
Edit:
But it can be improved a bit:
function flashtext(ele,col) {
var style = document.getElementById(ele).style;
(function main(){
var cond=style.color === 'grey';
style.color=cond?col:'grey';
setTimeout(main,cond?1400:700);
})();
}
flashtext('flashingtext','yellow');
DEMO: http://jsfiddle.net/EfpEP/3/
Alnitak had the great idea of storing the color because the browser can change it to another syntax. But his code is calling document.getElementById each time. Then, taking his idea, I think the best way is:
function flashtext(ele,col) {
var style = document.getElementById(ele).style,
cond=style.color === 'grey';
(function main(){
cond=!cond;
style.color=cond?col:'grey';
setTimeout(main,cond?1400:700);
})();
}
flashtext('flashingtext','yellow');
DEMO: http://jsfiddle.net/EfpEP/4/
Edit 2:
But if you are going to use something like
flashtext('flashingtext','yellow');
flashtext('flashingtext2','blue');
...
you will end up freezing the browser.
Instead, you should use
function FlashText(){
var arr=[],
cond=false,
started=false;
this.add=function(el,col){
if(typeof el==='string'){el=document.getElementById(el);}
arr.push([el.style,col]);
}
this.start=function(){
if(started){return;}
started=true;
main();
}
function main(){
cond=!cond;
for(var i=0,l=arr.length;i<l;i++){
arr[i][0].color=cond?arr[i][1]:'grey';
}
setTimeout(main,cond?1400:700);
};
}
var flash=new FlashText();
flash.add('flashingtext','yellow');
flash.add('flashingtext2','blue');
flash.start();
You can also call passing an element by reference: flash.add(document.getElementById('flashingtext'),'yellow') (maybe you have a variable which contains an element which has no id).
But try not to add more elements after flash.start(). If you do that, the element will be black (or default color) until main is called (maybe 1.4 seconds).
DEMO: http://jsfiddle.net/EfpEP/6/
Related
So I have created this javascript that animates a certain place using it's ID.
The problem is that there are many of those on the site and meaning this I'd have to duplicate this function a lot of times just to replace the x in getElementById("x").
So here is the code I fully done by myself:
var popcount = 0;
var opanumber = 1;
var poptimeout;
function pop() {
if (popcount < 10) {
popcount++;
if (opanumber == 1) {
document.getElementById("nav1").style.opacity = 0;
opanumber = 0;
poptimeout = setTimeout("pop()", 50);
}
else {
document.getElementById("nav1").style.opacity = 1;
opanumber = 1;
poptimeout = setTimeout("pop()", 50);
}
}
else {
popcount = 0;
document.getElementById("nav1").style.opacity = 1;
}
}
function stoppop() {
clearTimeout(poptimeout);
popcount = 0;
document.getElementById("nav1").style.opacity = 1;
}
I would gladly appreciate any information on how I could solve this situation and also any tutorials about using classes and "this".
Something like this; rather than hard code a value into a function it is better to pass the value in so you can reuse the function on more than one thing. In this case you can now call startPop and stopPop with the name of a CSS class.
var popTimeout;
function setOpacity(className, value) {
Array.prototype.forEach.call(
document.getElementsByClassName(className),
function(el) {
el.style.opacity = value;
}
);
}
function pop(className, popCount, opaNumber) {
if (popCount < 10) { //Must be even number so you end on opacity = 1
setOpacity(className, opaNumber);
popTimeout = setTimeout(function() {
pop(className, popCount++, 1-opaNumber);
}, 50);
}
}
function startPop(className) {
pop(className, 0, 0);
}
function stopPop(className) {
clearTimeout(popTimeout);
setOpacity(className, 1);
}
In case you are wondering about the 1 - opaNumber; this is a simpler way of switching a value between 1 and 0. As 1-1=0 and 1-0=1.
Well you started out with recognizing where you have the problem and that's already a good thing :)
To make your code a bit more compact, and get as many things as possible out of the local scope, you could check the following implementation.
It is in a sense a small demo, where I tried adding as much comments as possible.
I edited a bit more after realizing you rather want to use classnames instead of id's :) As a result, I am now rather using the document.querySelectorAll that gives you a bit more freedom.
Now you can call the startPop function with any valid selector. If you want to pop purely on ID, you can use:
startPop('#elementId');
or if you want to go for classes
startPop('.className');
The example itself also add's another function, nl trigger, that shows how you can start / stop the functions.
I also opted to rather use the setInterval method instead of the setTimeout method. Both callback a function after a certain amount of milliseconds, however setInterval you only have to call once.
As an extra change, stopPop also now uses the document.querySelectorAll so you have the same freedom in calling it as the startPop function.
I added 2 more optional parameters in the startPop function, namely total and callback.
Total indicates the maximum times you wish to "blink" the element(s), and the callback provides you with a way to get notified when the popping is over (eg: to update potential elements that started the popping)
I changed it a bit more to allow you to use it for hovering over an element by using the this syntax for inline javascript
'use strict';
function getElements( className ) {
// if it is a string, assume it's a selector like #id or .className
// if not, assume it's an element
return typeof className === "string" ? document.querySelectorAll( className ) : [className];
}
function startPop(className, total, callback) {
// get the element once, and asign a value
var elements = getElements( className ),
current = 0;
var interval = setInterval(function() {
var opacity = ++current % 2;
// (increase current and set style to the left over part after dividing by 2)
elements.forEach(function(elem) { elem.style.opacity = opacity } );
// check if the current value is larger than the total or 10 as a fallback
if (current > (total || 10)) {
// stops the current interval
stopPop(interval, className);
// notifies that the popping is finished (if you add a callback function)
callback && callback();
}
}, 50);
// return the interval so it can be saved and removed at a later time
return interval;
}
function stopPop(interval, className) {
// clear the interval
clearInterval(interval);
// set the opacity to 1 just to be sure ;)
getElements( className ).forEach(function(elem) {
elem.style.opacity = 1;
});
}
function trigger(eventSource, className, maximum) {
// get the source of the click event ( the clicked button )
var source = eventSource.target;
// in case the attribute is there
if (!source.getAttribute('current-interval')) {
// start it & save the current interval
source.setAttribute('current-interval', startPop(className, maximum, function() {
// completed popping ( set the text correct and remove the interval )
source.removeAttribute('current-interval');
source.innerText = 'Start ' + source.innerText.split(' ')[1];
}));
// change the text of the button
source.innerText = 'Stop ' + source.innerText.split(' ')[1];
} else {
// stop it
stopPop(source.getAttribute('current-interval'), className);
// remove the current interval
source.removeAttribute('current-interval');
// reset the text of the button
source.innerText = 'Start ' + source.innerText.split(' ')[1];
}
}
<div class="nav1">
test navigation
</div>
<div class="nav2">
Second nav
</div>
<div class="nav1">
second test navigation
</div>
<div class="nav2">
Second second nav
</div>
<a id="navigation-element-1"
onmouseover="this.interval = startPop( this )"
onmouseout="stopPop( this.interval, this )">Hover me to blink</a>
<button type="button" onclick="trigger( event, '.nav1', 100)">
Start nav1
</button>
<button type="button" onclick="trigger( event, '.nav2', 100)">
Start nav2
</button>
If you do want to take it back to using IDs, then you will need to think about popTimeout if you run this on more than one element at a time.
function setOpacity(id, value) {
document.getElementById(id).style.opacity = value;
}
function runPop(id) {
function pop(id, popCount, opaNumber) {
if (popCount < 10) { //Must be even number so you end on opacity = 1
setOpacity(id, opaNumber);
popTimeout = setTimeout(function() {
pop(id, popCount++, 1-opaNumber);
}, 50);
}
}
var popTimeout;
pop(id, 0, 0);
return function() {
clearTimeout(popTimeout);
setOpacity(id, 1);
}
}
var killPop = [];
function startPop(id) {
killPop[id] = runPop(id);
}
function stopPop(id) {
killPop[id]();
}
I need to make my Jira page on internal network show my assignee name in red color using a userscript without any external code use - no jQuery etc. And be as simple as possible, as I'm just learning.
Example page is here (List view): https://jira.atlassian.com/issues/?filter=-5
My internal page has following tag with my name in it, like this:
<a class="user-hover" rel="myusername" id="assignee_myusername" href="https://jira.mydomain.org/secure/ViewProfile.jspa?name=myusername" target="_parent">Myfirstname Mylastname</a>
My userscript is only making color changes on top and bottom lines of the page (I am logged in; it changes most links for userspecific ones). But the middle, where list of cases and assignees is listed, doesn't get affected. Here is my script:
// ==UserScript==
// #name Jira
// #namespace https://jira.mydomain.org/secure/Dashboard.jspa
// #include https://jira.mydomain.org/*
// ==/UserScript==
var links = document.getElementsByTagName( 'a' );
var element;
for ( var i = 0; i < links.length; i++ ) {
element = links[ i ];
if ( element.id = "assignee_myusername" ) {
element.style.color = "red";
element.style.backgroundColor = "black";
}
}
How do I make it highlight my name in Assignee column?
P.S. This is not same as the Ajax question, as that uses external code, which I specified in the beginning - no external code. No external code.
My guess is that the parts of the Jira page you want to script have not been loaded when your user script executes. Jira uses Ajax to load parts of the page asynchronously. Try adding a setTimeout around your code:
window.setTimeout(function () {
var links = document.getElementsByTagName( 'a' );
var element;
for ( var i = 0; i < links.length; i++ ) {
element = links[ i ];
if ( element.id = "assignee_myusername" ) {
element.style.color = "red";
element.style.backgroundColor = "black";
}
}
}, 1000);
This will highlight the link after one second. It's a hacky solution, but if it works, then that at least will show you that the async loading is, in fact, the problem.
If you just want to change the style of an element with ID “assignee_myusername”, you don't need to use getElementsByTagName, you can use getElementById:
window.setTimeout(function () {
var element = document.getElementById( 'assignee_myusername' );
element.style.color = "red";
element.style.backgroundColor = "black";
}, 1000);
I want to change the coilor of a button on mouse click from white to red then from red back to white if click again. I tried like this:
<script language="JavaScript">
<!--
function changecolor(Id){
var series = "0";
var a = window.getComputedStyle(document.getElementById(Id)).backgroundColor;
var b = 2
if (a == "#FF4F4F") {
b = 1
}
if (b == 1) {
document.getElementById(Id).style.backgroundColor = "#FFFFFF";
}
if (b == 2) {
document.getElementById(Id).style.backgroundColor = "#FF4F4F";
}
}
//-->
</script>
It won't work. This will make the button go red in mozilla, chrome but it won't click back to white. IE says "error in page". The button HTML code is:
<input type = "button" Id = "01" value="01" onClick="changecolor('01')">
Something missing from my CSS styles. It looks like the first read (of the colour) is a null value but it does makes the button go red -in the two browsers- the way this function of mine is constructed. Then it looks like the if condition is not working properly, to see the red and make it white.
The computed style of a background colour is of the format rgb(###, ###, ###) (or variations thereof, such as different whitespace or rgba) Therefore comparing with #xxxxxx will not work.
Since you're assigning to style.backgroundColor, you can simply read back:
var elem = document.getElementById(Id);
if( elem.style.backgroundColor == "#FF4F4F") {
elem.style.backgroundColor = "#FFFFFF";
}
else {
elem.style.backgroundColor = "#FF4F4F";
}
Feel free to switch the cases around as needed (based on how it should change the first time), but this will work because the browser will keep whatever you assigned to it.
However, in general, you should have a more reliable toggle:
var elem = document.getElementById(Id);
if( elem._toggle) {
elem.style.backgroundColor = "#FFFFFF";
}
else {
elem.style.backgroundColor = "#FF4F4F";
}
elem._toggle = !elem._toggle;
This will toggle reliably.
EDIT 2 - I decided to create a simple example with jsfiddle.
http://jsfiddle.net/VqA9g/61/
As you can see, I am trying to reference the new div.
EDIT - d/t negative votes and unclear question
I have a linked-list like so:
var struct_list = function () {
this.id = 0;
this.name = 0;
this._head = null;
};
struct_list.prototype = {
// .. adding code , delete code ...
list_contents: function () {
var current = this._head;
while ( current != null ) {
var div = document.createElement("div");
div.style.width = "100px";
div.style.height = "100px";
div.style.background = "white";
div.style.color = "black";
div.style.top = "0px";
div.style.left = "0px";
div.style.margin = "400px 1000px auto";
div.style.cursor = "pointer";
div.innerHTML = current.name;
div.onclick = function ( v ) { var d = document.getElementById('div'); alert(d)};
document.body.appendChild(div);
current = current.next;
}
return null;
},};
I want to be able to display this linked list, and each item displayed be able to interact with an "onclick".
Example:
struct_list.add ( 0 , "Zero" );
struct_list.add ( 1 , "One" );
struct_list.list_contents();
_________________________________________________________________________
| |
| <clickable> "Zero" that does a function(id) that passes over its ID(0) |
|________________________________________________________________________|
| |
| <clickable> "One" <same as above> |
|________________________________________________________________________|
Sorry if I was unclear. Will reedit if still unclear. My apologies.
I have a linked-list struct that I hold data in (it changes data frequently) and I have a setInterval to refresh it. My question is how can I list the struct's contents while still being able to click the exposed content, I have it set up right now that each content in the linked-list contains an id. Also , how can I make sure that overflow is automatic for the y axis? I am guessing I have to place it into a div that has that enabled.
But my real question is how to expose the linked-lists elements while also being able to interact with them via an onclick.
I also do not want to use anything other than pure javascript.
Example (in my mind) would maybe be something like:
<div id="PopUp">
<script>
setInterval(function() {
if ( struct_qued_list ) {
struct_qued_list = false;
main.struct_list.list_contents(); // the linked list
}
}, 100);
</script>
</div>
list_contents: function () {
var current = this._head;
while ( current != null ) {
var div = document.createElement("div");
div.style.width = "100px";
div.style.height = "100px";
div.style.background = "white";
div.style.color = "black";
div.style.top = "0px";
div.style.left = "0px";
div.style.margin = "400px 1000px auto";
div.style.cursor = "pointer";
div.innerHTML = current.name;
div.onclick = function ( v ) { var d = document.getElementById('div'); alert(d)};
document.body.appendChild(div);
current = current.next;
}
return null;
},
Any help or logical way to do this would be appreciated.
This is mainly a scope problem, in your Edit 2 fiddle, the alert gives undefined because your i got the value 2 in order to leave the loop.
Here is a possible solution : Live demo (jsfiddle)
!function(){
var index = i; // Make it independant of i
div.onclick = function () { alert(list[index]); };
}();
You could also use attributes to store any value, and using this in the function to retrieve it.
Or export the whole process to another function to obtain something like this :
for ( var i = 0; i < 2 ; i++ ) {
doSomething(i);
}
When you add new content to the DOM JavaScript sometimes has a hard time picking that up. You may need to use a DOM mutation event (like DOMNodeInserted) to add the event listeners to your text nodes.
document.addEventListener('DOMNodeInserted', function(){
document.getElementById('thing').addEventListener('click', function(){
alert('yey!');
});
});
you may need to name your functions so you can remove them as well, if nodes are going to be inserted without removing all the old ones. Yes this is pure javascript.
EDIT: for your overflow issue, you could assign a class to each node as you insert it and style the class via CSS
.classname {
overflow: auto;
}
I want either remove or reset a style applied on a particular DOM node using JS.
node.style.webkitTransitionDuration = '5000ms';
node.style.webkitTransformOrigin = '200px 200px';
node.style.webkitTransform = 'rotateZ(25rad)';
I want to reset/set webkitTransform time and again on a fire of an event
Tried like this
node.style.webkitTransform = 'rotateZ(0rad)';
node.style.webkitTransform = 'rotateZ(25rad)';
But its not working.
P.S. Can not use any framework.
Here's an example that should fit your needs. It toggles when you click on the document. Note: it of course only works in Webkit-based browsers.
animateNode(document.getElementById("test"), "5000ms", "200px 200px", "rotateZ(25rad)");
var toggle = toggleValue();
function animateNode(node, duration, origin, transform)
{
node.style['webkitTransitionDuration'] = duration;
node.style['webkitTransformOrigin'] = origin;
node.style['webkitTransform'] = transform;
}
function toggleValue() {
var num = 1;
return function ()
{
return ++num;
};
}
document.onclick = function()
{
var toggleNum = toggle();
if(toggleNum % 2 === 0)
{
animateNode(document.getElementById("test"), "5000ms", "200px 200px", "rotateZ(0rad)");
}else if(toggleNum % 2 === 1)
{
animateNode(document.getElementById("test"), "5000ms", "200px 200px", "rotateZ(25rad)");
}
}
http://jsfiddle.net/GdGw7/3/
If you are looking to remove the rule from the element then this should work:
node.style.webkitTransform = '';
You say you don't want to use a framework. but if it is OK (according to your comment) to do so:
You can use jQuery:
so you can do in jQuery:
$('selector').css({
webkitTransitionDuration = '5000ms',
webkitTransformOrigin = '200px 200px',
webkitTransform = 'rotateZ(25rad)'
})
you can clear out the style element with:
$('selector').attr('style','');
add class:
$('selector').addClass('newClass');
remove class:
$('selector').removeClass('rClass');