How to make animate drawing a border? (Vanilla JS solution needed) - css-animations

I am trying to build a relaxation app.
For this I need to get a animation of border being drawn.
The way I tried is not giving a smooth transition.
How to achieve the same?
A part of javascript code and codepen link is shared below
https://codepen.io/TM06/pen/RwrRxLQ
JS
if(count && seconds<=4){
document.getElementById("message").innerText = "Breathe In";
switch(seconds){
case 1 :
document.getElementById("container").style.borderTop = "8px solid red";
break;
case 2 :
document.getElementById("container").style.borderRight = "8px solid red";
break;
case 3 :
document.getElementById("container").style.borderBottom = "8px solid red";
break;
case 4 :
document.getElementById("container").style.borderLeft = "8px solid red";
break;
}
}else if(count === false && seconds< 5){
document.getElementById("message").innerText = "Breathe Out";
switch(seconds){
case 1 :
document.getElementById("container").style.borderLeft = "0px";
break;
case 2 :
document.getElementById("container").style.borderBottom = "0px";
break;
case 3 :
document.getElementById("container").style.borderRight = "0px";
break;
case 4 :
document.getElementById("container").style.borderTop = "0px";
break;
}
}

I have acheived the border animation. Sharing the codepen link here:
https://codepen.io/TM06/pen/wvMgeaw
<div class="container h-100 align-items-center" id="container">
<div class="topBar" id="topBar"></div>
<div class="rightBar" id="rightBar"></div>
<div class="bottomBar" id="bottomBar"></div>
<div class="meter9"><span class="leftBar" id="leftBar"></span></div>
This is not yet perfect though.

Related

Using document.getElementsByClassName in Testcafe

I have a menu that always has the same structure, but the IDs can change from one installation to another. the only thing that stays the same is the heading (in my case "Plugins"). I call the document.getElementsByClassName function with a Selector inside my test:
var slides = Selector(() =>{
return document.getElementsByClassName("c-p-header-text");
});
Every heading of an menu element has the c-p-header-text class. Here is what a menu heading element looks like:
<div id="ext-comp-1002" class="c-p c-tree c-p-collapsed" style="width: auto;">
<div class="c-p-header c-unselectable c-accordion-hd" id="ext-gen135" style="cursor: pointer;">
<div class="c-tool c-tool-toggle" id="ext-gen140"> </div>
<img src="/backEnd/images/s.gif" class="c-p-inline-icon order"><span class="c-p-header-text" id="ext-gen150">Plugins</span>
</div>
It would be easy to use await t.click("#ext-gen150") but it is not safe that it is always this id.
here is what i tried:
await t
.click('#sites__db');
var slides = Selector(() =>{
return document.getElementsByClassName("c-p-header-text");
});
console.log("[DEBUG]" + slides);
console.log("[DEBUG] found " + slides.length + " elements");
for(var i = 0; i < slides.length; i++)
{
var txtOfCurrElem = slides.item(i).innerText;
console.log("[DEBUG "+ i +"] Text: " + txtOfCurrElem);
}
Running this test give me the following output:
[DEBUG]function __$$clientFunction$$() {
var testRun = builder.getBoundTestRun() || _testRunTracker2.default.resolveContextTestRun();
var callsite = (0, _getCallsite.getCallsiteForMethod)(builder.callsiteNames.execution);
var args = [];
// OPTIMIZATION: don't leak `arguments` object.
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}return builder._executeCommand(args, testRun, callsite);
}
[DEBUG] found 0 elements
The plan is to find the element (with the heading "Plugins") and then click on it when the test continuous.
You don't have to use document.getElementsByClassName in this case. You can just use CSS class selector instead:
var slides = Selector('.c-p-header-text');
You should use the count property when dealing with an array of Selectors. docs. Also, element properties, like exists, count, and DOM node state properties are Promisified, so when you use them not in t.expect, you should use the await keyword:
var count = await slides.length;
console.log("[DEBUG] found " + count + " elements");
for(var i = 0; i < count; i++)
{
var txtOfCurrElem = await slides.nth(i).innerText;
console.log("[DEBUG "+ i +"] Text: " + txtOfCurrElem);
}
I found a simple answer to my question. I use the .withText option to click on the Plugins element:
.click(Selector('span').withText("Plugins"))
Since this name is also unique, it is always the correct element that gets clicked. I do not know if it would have worked with the solution from #AndreyBelym if my site is not an extJS web application.

vendor prefix pseudo-selector crashes element.matches() Web API in Safari

I'm building a utility into a style guide generator that automatically gathers the CSS for each element and displays it adjacent to the element in the output. The script I'm using to gather and parse the CSS is based on an answer from SO and uses the element.matches() web API.
Under most circumstances the code works perfectly, but in cases where there is a 'vendor prefix'-specific pseudo-element selector (e.g. ::-webkit-inner-spin-button as in Bootstrap 4.0), Safari throws an error at the most nested if statement (i.e. if (a.matches(rules[r].selectorText)) {):
SyntaxError (DOM Exception 12): The string did not match the expected pattern.
I've tried searching for this error specifically on SO and I found this question that talks about missing array endings, but I don't think the answer pertains to my issue.
I have a regex workaround that will remove the offending rules so the function can at least run, but as you can see, the properties in that rule ({background-color:black;}) are completely ignored in the output even though they're applied to the rendered element.
I could modify my regex to parse the strings and slice out problematic selectors while leaving the parsable rules, but overall this type of very specific hack feels inelegant to me, and I'm concerned it may cause problems down the road if my team ends up adding rules that rely on those types of vendor-prefixed pseudo-selectors.
Any ideas on how I can be a little more precise about working around (or solving) this issue?
Working Snippet
window.css = function (a) {
var sheets = document.styleSheets, o = [];
a.matches = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.msMatchesSelector || a.oMatchesSelector;
for (var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for (var r in rules) {
if (a.matches(rules[r].selectorText)) {
o.push(rules[r].cssText);
}
}
}
return o;
}
$(document).ready(function(){
$('button').on('click',function(){
$('#styles').text(css( $( $('input').val() )[0] ));
});
});
div * {border-left:2px solid black;margin:1em 0;padding:.5em;}
a {text-decoration:none;display:block;cursor:pointer;}
#red {color:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="#red"><button>Get styles</button>
<div>
<a id="red">#red anchor</a>
</div>
<aside id="styles"></aside>
Broken Snippet
(only change is 1 added line of CSS)
window.css = function (a) {
var sheets = document.styleSheets, o = [];
a.matches = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.msMatchesSelector || a.oMatchesSelector;
for (var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for (var r in rules) {
if (a.matches(rules[r].selectorText)) {
o.push(rules[r].cssText);
}
}
}
return o;
}
$(document).ready(function(){
$('button').on('click',function(){
$('#styles').text(css( $( $('input').val() )[0] ));
});
});
div * {border-left:2px solid black;margin:1em 0;padding:.5em;}
a {text-decoration:none;display:block;cursor:pointer;}
#red {color:red;}
/* v ADDED THIS LINE - THIS IS THE ONLY CHANGE v */
[type="submit"]::-webkit-inner-spin-button {background-color:black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="#red"><button>Get styles</button>
<div>
<a id="red">#red anchor</a>
</div>
<aside id="styles"></aside>
Reg-Ex Workaround
window.css = function (a) {
var sheets = document.styleSheets, o = [];
a.matches = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.msMatchesSelector || a.oMatchesSelector;
// v NEW FUNCTION v
function removeVendorPrefixSelectors (selectorText) {
if (/::-/.test(selectorText)) {
//do nothing
} else {
return selectorText;
}
}
for (var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for (var r in rules) {
// v NEW LINE v
rule = removeVendorPrefixSelectors(rules[r].selectorText);
if (a.matches(rule)) {
o.push(rules[r].cssText);
}
}
}
return o;
}
$(document).ready(function(){
$('button').on('click',function(){
$('#styles').text(css( $( $('input').val() )[0] ));
});
});
div * {border-left:2px solid black;margin:1em 0;padding:.5em;}
a {text-decoration:none;display:block;cursor:pointer;}
#red {color:red;}
a, [type="submit"]::-webkit-inner-spin-button {background-color:black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="#red"><button>Get styles</button>
<div>
<a id="red">#red anchor</a>
</div>
<aside id="styles"></aside>

How to get the children-item in listItem of a listView (Titanium)?

I had defined an imageview in my layout for the individual items of a list, and they were set invisible. When I clicked a button, they will be show,but I can't get this action act. I want to achieve this effect. Here is my code:
//file:list_view_test.jade
Alloy
Window#win
Button#btn(title = "Show" onClick = "show_the_image_view")
ListView#list_view(defaultItemTemplate = "list_style")
Templates
ItemTemplate(name = "list_style")
View#item_view(bindId = "bind_item_view")
ImageView#image_view(bindId = "bind_image_view")
ListSection
ListItem(bind_item_view:backgroundImage = "/images/backgroundImage_1.png"
bind_image_view:image = "/images/unchecked_image.png")
ListItem(bind_item_view:backgroundImage = "/images/backgroundImage_2.png"
bind_image_view:image = "/images/unchecked_image.png")
//file:list_view_test.stss
#item_view{
width:100%;
height:10%
}
#image_view{
top:0;
left:0;
width:20%;
height:20%;
visible:false
}
//file:list_view_test.coffee
show_the_image_view = ->
if "Show" == $.btn.getTitle()
$.btn.setTitle("Hide")
//$.image_view.setVisible(true) (this code had been commented, cause it's wrong)
else if "Hide" == $.btn.getTitle()
$.btn.setTitle("Show")
//$.image_view.setVisible(false) (this code had been commented, cause it's wrong)
$.list_view.addEventListener('itemclick', = (e) ->
if e.itemIndex == 0
//$.image_view.setImage('/images/checked_image.png') (this code had been commented, cause it's wrong)
else if e.itemIndex == 1
//$.image_view.setImage('/images/checked_image.png') (this code had been commented, cause it's wrong)
Is there anyone who has a good method to solve the problem?

MultiDPIBitmapSource in BitmapFill doesn't work

MultiDPIBitmapSource in BitmapFill doesn't work.
Here is my code:
`
<s:Rect id="background2" left="0" right="0" top="0" bottom="0" percentWidth="100" percentHeight="100" radiusX="20" >
<s:fill >
<s:BitmapFill id="bgFill" fillMode="repeat">
<s:source>
<s:MultiDPIBitmapSource source160dpi="#Embed('images/backgroundSki/240/abiSefid.jpg')"
source240dpi="#Embed('images/backgroundSkin/240/abiSefid.jpg')"
source320dpi="#Embed('images/backgroundSkin/320/abiSefid.jpg')" />
</s:source>
</s:BitmapFill>
</s:fill>
</s:Rect>`
work with flash builder some times become so much complicated than another sdk's like visual stadio... we should take care about detail for example in MultiDPIBitmapSource help of flash builder say's:
This class provides a list of bitmaps for various runtime densities.
It is supplied as the source to BitmapImage or Image and as the icon
of a Button
. The components will use the Application.runtimeDPI to choose which image to display.
so we cant use MultiDPIBitmapSource in bitmapFill in rect . also we maybe want use this code for solve problem:
<fx:Script>
<![CDATA[
.
.
switch( FlexGlobals.topLevelApplication.runtimeDPI)
{
case DPIClassification.DPI_240 :
bgFill.source = "images/backgroundSkin/160/image.jpg
break;
case DPIClassification.DPI_160 :
bgFill.source = "images/backgroundSkin/160/image.jpg
break;
case DPIClassification.DPI_320 :
bgFill.source = "images/backgroundSkin/160/image.jpg
break;
}
.
.
]]>
</fx:Script>
.
.
<s:Rect id="background2" left="0" right="0" top="0" bottom="0" width="100%" height="100%" >
<s:fill>
<s:BitmapFill id="bgFill" fillMode="repeat" />
</s:fill>
</s:Rect>
but you can see this code also dont work i think the id of BitmapFill is anknown in script code .. any way the only way that worked for me was using of loader :
.
.
.switch( FlexGlobals.topLevelApplication.runtimeDPI)
{
case DPIClassification.DPI_240 :
loader.load(new URLRequest("images/backgroundSkin/240/image.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
break;
case DPIClassification.DPI_160 :
loader.load(new URLRequest("images/backgroundSkin/160/image.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
break;
case DPIClassification.DPI_320 :
loader.load(new URLRequest("images/backgroundSkin/320/image.jpg"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
break;
}
}
public function loaderCompleteHandler(evt:Event):void
{
bgFill.source = evt.target.content;
}

Adding atrribute to all elements with specifeid class using js

*JS*
document.getElementsByClassName('abc')[0].setAttribute('id', 'abe');
*html*
<div class="abc"></div>
<div class="abc"></div>
How to make this script work with more than one element?
Some thing like this
var divs = document.getElementsByClassName('abc');
for (i = 0; i < divs.length; i++) {
divs[i].setAttribute('id', 'abe');
}