I've built a widget in ServiceNow that displays a user's onboarding steps and when a step is clicked upon, a div appears below that lists out all of the tasks that they need to complete. While this works fine, I think it would look slicker if instead of having a div appear below the onboarding steps with a line divider, that the list of tasks would take the place of the entire onboarding steps div. Then maybe have a back button that takes them back to the onboarding steps with some fade in/fade out animation. If possible, I would like this to be done without jquery. Can someone provide some guidance or direct me towards an example?
My HTML so far looks like this:
<div class="container" ng-if="!c.data.loading && c.stage.length>0">
<div class="parent">
<div class="child" ng-repeat="item in c.stage track by $index">
<div class="at-work-process position-relative overflow-hidden text-center">
<div class="at-work-process-text">
<span class="at-work-process-step" ng-class="{inactive: item.workflow_order>c.currentOrder}">Step</span>
<span class="at-work-process-number" ng-class="{inactive: item.workflow_order>c.currentOrder}">{{$index+1}}</span>
<span class="at-work-process-number-text" ng-class="{inactive: item.workflow_order>c.currentOrder}">{{item.workflow_stage}}</span>
<div class="at-separator-thick" ng-class="{active_stage: item.currentStage, completed_stage: item.incompleteTotal==0 && item.workflow_order<c.currentOrder}"></div>
</div>
<div ng-click="showDetails(item);" class="at-work-process-details" ng-class="{inactive: item.workflow_order>c.currentOrder}">
<div ng-if="item.incompleteTotal>0 && item.workflow_order<=c.currentOrder" class="full-height">
<i class="material-icons" style="color:#e53935;">assignment_late</i>
<span ng-if="item.incompleteTotal>1">Incomplete <br/> {{item.incompleteTotal}} Tasks Require Your Attention</span>
<span ng-if="item.incompleteTotal==1">Incomplete <br/> {{item.incompleteTotal}} Task Require Your Attention</span>
</div>
<div ng-if="item.incompleteTotal==0 && item.workflow_order>c.currentOrder" class="full-height">
<i class="material-icons" style="color:#78B4F3;">assignment</i>
<span>Not Started</span>
</div>
<div ng-if="item.incompleteTotal==0 && item.workflow_order<c.currentOrder" class="full-height">
<i class="material-icons" style="color:#43A047;">assignment_turned_in</i>
<span>Complete</span>
</div>
</div>
</div>
</div>
</div>
//am hoping the below div would take the place of the above div instead of showing up underneath it//
<div ng-if="active_tasks.length>0" ng-class="taskClass" class="text-center tasksDiv">
<md-divider></md-divider>
<h3>{{active_workflow}} Tasks:</h3>
<ul style="list-style:none; padding-left:0; display:inline-block">
<li ng-repeat="tasks in active_tasks track by $index" style="display:flex; align-items:center; padding-bottom:0.5rem;">
<i class="material-icons" style={{tasks.style}}>{{tasks.icon}}</i>
<a ng-if="tasks.url.indexOf('table2')!=-1" ng-click="c.enroll(tasks)" href="javascript: void(0)" ng-class="{completed_inactive: tasks.state==3}">{{tasks.short_description}}</a>
<a ng-if="tasks.url.indexOf('table1')!=-1" ng-click="c.tableNew()" href="javascript: void(0)"ng-class="{completed_inactive: tasks.state==3}">{{tasks.short_description}}</a>
<a ng-if="tasks.hr_task_type=='url' && tasks.url.indexOf('c.')==-1" href="{{tasks.url}}" target="_blank" ng-class="{completed_inactive: tasks.state==3}">{{tasks.short_description}}</a>
<a ng-if="tasks.url.indexOf('launchWith')!=-1" ng-click="c.launchWith()" href="javascript: void(0)" ng-class="{completed_inactive: tasks.state==3}">{{tasks.short_description}}</a>
<a ng-if="tasks.hr_task_type!='url'" ng-click="review(tasks)" href="javascript: void(0)" target="_blank" ng-class="{completed_inactive: tasks.state==3}">{{tasks.short_description}}</a>
</li>
</ul>
</div>
</div>
I would attach an ng-if to the first div that works on the opposite condition of the second div.
So in this case, your second div has ng-if="active_tasks.length>0" as its condition for display. So you could set an ng-if="active_tasks.length<=0" on the first div so that any time the second div is displayed, the condition will be false for the first div. Then just remove the divider in the second div (since you don't want that anymore). Now when you perform an action on the first div and active_tasks gets populated, the first one will be destroyed and the second one will be created.
Note that in this case, you're using ng-if which will create/destroy DOM elements. You can also use ng-show to show/hide the DOM elements if you anticipate the user going back and for a lot (so that they're created up front and just hidden instead of being recreated each time the user changes the state)
Your html is slightly hard to follow, so I'm not sure which blocks you would like to hide/show, but you can do this very simply. Just create a variable, showTaskList on your scope and set it to true/false. Then on the parent div for the onboarding list do, ng-if="!showTaskList" and on the parent div for the task list, ng-if="showTaskList".
When the person clicks the button to switch between the task list or the onboarding steps, just switch this bool to the opposite, showTaskList = !showTaskList.
Related
I have an issue with using tab navigation or screen reader.
I have a bunch of divs with list inside of it, where each list item has a link, as shown in example below. This html represents vertical "carousel", where user can vertically scroll across the items.
The entire carousel is shown inside of popover (if it matters at all). And it has a lot of CSS to keep carousel scrollable(overflow:hidden, not sure if it matters).
While testing the widget for Accessibility, I found an issue:
Carousel container is not focusable when using tab navigation or screen reader. So, the entire container is just skipped by ScreenReader (Voice Over) and it never goes inside container to read the links.
I tried to add tabindex="-1" for the top most div element, and now it receives the focus, however, it doesn't go inside the div to go through the links.
What can be the reasons for that? How can I make VoiceOver not skip the content and go through all the links
<div class="a-carousel-viewport" id="carousel">
<ol class="carousel" role="list" aria-busy="false">
<li class="carousel-card" role="listitem" aria-setsize="12" aria-posinset="11" aria-hidden="true">
<div class="item">
<h4>Title 1</h4>
<a aria-hidden="true" class="a-link-normal vse-carousel-item" tabindex="-1" href="/someurl">
<div class="content">
</div>
</a>
</div>
</li>
<li class="carousel-card" role="listitem" aria-setsize="12" aria-posinset="11" aria-hidden="true">
<div class="item">
<h4>Title 2</h4>
<a aria-hidden="true" class="a-link-normal vse-carousel-item" tabindex="-1" href="/someurl">
<div class="content">
</div>
</a>
</div>
</li>
</ol>
</div>
It's hard to check the behaviour just from the HTML, a JSfiddle or CodePen to include the JavaScript would help a lot. However, you've got a lot of ARIA attributes that aren't necessary and might be confusing VoiceOver.
The first thing I'd try if you can't provide a demo of the problem behaviour is to remove all of the role and aria-attributes from your code sample and see if that fixes the problem. The roles for list and listitem are redundant on list (ol) and list item (li) elements. aria-setsize and aria-posinset are also not needed on lists. Tabindex and aria-hidden might be needed depending on how the carousel hides slides which aren't visible, but if removing the roles and aria-attributes doesn't help, it might be useful to remove them and see if VoiceOver can find the links when you do.
I developed a timeline, however I am having some issues that I can't solve :(
Firstly, the timeline is not responsive, ie when the screen enlarges or I put a larger description, the timeline lines separate and I always want to have it together, does anyone know what it is?
Second problem: Timeline starts at value 1, how can I always start at value 4?
As you can see in the image, I have both problems: separate timeline lines and it starting at 1 and not 4 :(
HTML
<ul class="timeline" id="timeline" *ngFor="let priority of Priorities; let p = index;">
<li class="li complete">
<div class="timestamp">
<span class="priorityNumber">{{priority.id}}</span>
</div>
<div class="status">
<span class="circle"></span>
<h4 class="timelineh4">{{priority.text}}</h4>
</div>
</li>
</ul>
Seen your code, If you are using angular then why are you doing it the javascript way.
And fixed as much I can in this fork. I cant understand your second question's requirement Please brief on it.
I want to create an accordion with nested levels. So I have used Angular's accordion directive to create nested levels. But the last level contains a list which should get displayed one by one on new line. But what happens in my case all sub categories gets listed in one line.
I saw in the console that all sub categories are getting listed in one panel body. They should get separate class for each of the sub categories. Any one know how to do that? This is code of my accordion:
<div style='padding-top:50px;'>
<accordion>
<accordion-group heading="Title">
<accordion close-others="oneAtATime">
<accordion-group heading="Category">
<span>Subcat1</span>
<span>Subcat2</span>
</accordion-group>
</accordion>
</accordion-group>
</accordion>
</div>
Directive accordion-group is replacing following code:
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading">
<span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span>
</a>
</h4>
</div>
<div class="panel-collapse" collapse="!isOpen">
<div class="panel-body" ng-transclude>
</div>
</div>
</div>
So whatever I am printing inside <accordion-group></accordion-group> is getting placed in div having class panel-body. But as I am printing Subcat1 and Subcat2 inside accordion-group is going in one div panel-body. Like this:
<div ng-transclude="" class="panel-body">
<span class="ng-scope">Subcat1</span>
<span class="ng-scope">Subcat2</span>
</div>
But I want separate panel-body div for each of Subcat. Like
<div class="panel-body"><span>Subcat1</span></div>
<div class="panel-body"><span>Subcat1</span></div>
For more details see this plunker
Sorry for my english..:P
A <span> is defined as an inline element and will on its own not introduce any line breaks.
To achieve the output on multiple lines, you would either want to use elements that do that on their own, or make use of custom styles, usually via CSS.
If you really have a list of subcategories, you could for example use an ordered list <ol>.
Simple example:
<accordion>
<accordion-group heading="Title">
<accordion close-others="oneAtATime">
<accordion-group heading="Category">
<ol>
<li>Subcat1</li>
<li>Subcat2</li>
</ol>
</accordion-group>
</accordion>
</accordion-group>
Updated Plunker: Link
But this has nothing to do with your tags angularjs or the angular-ui accordion, it's an issue of plain HTML.
I'm trying to retreive "prace.avizo.cz" and "onlineprodej.cz" from the following html. I've tried several different variations to isolate that one url but none have been successful.
I'm trying to get it via an importXML function in a googledoc. Some of the paths I've tried are:
=importXML(B2,"//article[#class='genericlist component leadingReferers']//ul/li[1]")
=importXML(B2,"//ul[#class='sites items']//li[1]")
=importXML(B2,"//li[#class='item']//div//a")
These either don't work or return extra irrelevant data. I'm only looking for the data within this specific article class (genericlist component leadingReferers).
Any help is appreciated.
<article class="genericlist component leadingReferers">
<h2 class="title">
Top Publishers
<i class="tooltip sprite icon_tip_idle" title="<h1>Leading paid referring sites</h1>Leading publishers referring advertising traffic to Cz.indeed.com"></i>
</h2>
<ul class="sites items">
<li class="item ">
<div class="text" title="prace.avizo.cz" data-sitename="prace.avizo.cz">
<a class="link" href="/website/prace.avizo.cz" data-tipsygravity="w" data-shorturl="Prace.avizo.cz">
<img class="icon lazy-icon lazy" data-original="http://images2.similargroup.com/image?url=prace.avizo.cz&t=2&s=1&h=11351681863127555753" src="/images/lazy.png"/>
<noscript>
<img class="icon" src="http://images2.similargroup.com/image?url=prace.avizo.cz&t=2&s=1&h=11351681863127555753"/>
</noscript>
Prace.avizo.cz
</a>
</div>
<div class="progress-bar">
<div class="progress-value percentage per1" style="width: 62.91%"></div>
</div>
</li>
<li class="item ">
<div class="text" title="onlineprodej.cz" data-sitename="onlineprodej.cz">
<a class="link" href="/website/onlineprodej.cz" data-tipsygravity="w" data-shorturl="Onlineprodej.cz">
<img class="icon lazy-icon lazy" data-original="http://images2.similargroup.com/image?url=onlineprodej.cz&t=2&s=1&h=14252445317786093368" src="/images/lazy.png"/>
<noscript>
<img class="icon" src="http://images2.similargroup.com/image?url=onlineprodej.cz&t=2&s=1&h=14252445317786093368"/>
</noscript>
Onlineprodej.cz
</a>
</div>
<div class="progress-bar">
<div class="progress-value percentage per1" style="width: 50.88%"></div>
</div>
</li>
....
This expression will give you the last text node inside the <a> of the first item in the article:
//article[#class='genericlist component leadingReferers']//li[1]//a/text()[last()]
which is the one that contains the text Prace.avizo.cz (surrounded by spaces, tabs and newlines). If you wish to trim those extra spaces, you can pass that expression as the argument to the XPath function normalize-space():
normalize-space( //article[#class='genericlist component leadingReferers']//li[1]//a/text()[last()] )
You can select the second article in a similar manner (same expression, using li[2]):
//article[#class='genericlist component leadingReferers']//li[2]//a/text()[last()]
If you want to retrieve a collection containing all text nodes (which you can manupulate outside of XPath) you can use:
//article[#class='genericlist component leadingReferers']//li//a/text()[last()]
which will return a list containing all text nodes (two, in your example). In this case, you will have to use your host language to extract them (probably in a for-each loop).
I'm working on an application that displays a list of chats and need to get the chats into the virtual buffer. The chat content can be as simple as a line of text or as complicated as text plus a link plus an image. Without role=document, it's not in the buffer but with role=document JAWS reads "clickable" when it reads the content (after pressing down arrow). The content is not clickable and I can't figure out how to stop that from being read.
Here's an example of the layout:
<div role="application" class="mainViewContainer">
<ul class="mainViewContent">
<li tabindex="0" class="chatViewContainer">
<div tabindex="-1" class="chatHeaderContainer">
<span class="offscreen" id="chat1">Chat content</span>
<div role="document" tabindex="0" class="chatContent" aria-labelledby="chat1">
Here's a message, huzzah!
</div>
</div>
</li>
<li tabindex="0" class="chatViewContainer">
<div tabindex="-1" class="chatHeaderContainer">
<span class="offscreen" id="chat2">Chat content</span>
<div role="document" tabindex="0" class="chatContent" aria-labelledby="chat2">
<div class="chatText>Document documentName.jpg created </div>
<div class="documentView">
<img title="documentName.jpg" src="imgsrc">
<div class="documentItemDetails">
documentName.jpg
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
Any ideas on how to make the chatContent div not have "clickable" read by JAWS?
I'm seeing this with JAWS Version 15.0.6025 (I believe it's the most recent version) and FF 26 on Windows 7.
I had this same issue. Apparently, this is an expected behavior, as explained in this URL.
Clickable Text : When you navigate to a grid cell that has its display style set to clickable text, JAWS reads the corresponding column header text and then the data content of the current cell.
I hope this helps.