I have this code trying to delete the class
hello3:
var purify = require('purify-css');
var content = '<div class="hello"></div><div class="hello2"></div>';
var css = '.hello { color: green; } .hello3 { display: block; }';
var options = {
output: 'purified.css',
// Will minify CSS code in addition to purify.
minify: true,
// Logs out removed selectors.
rejected: true
};
purify(content, css, options);
The output in purified.css is the same as the variable css:
.hello { color: green; } .hello3 { display: block; }
How to solve it?
I ran a test and confirmed that purify-css doesn't like class names that contain numbers.
My command... purifycss css/main.css page1.html --out css/purified.css --info --rejected took my main.css file and incompletely purified it into:
.page1-h1 {
color: red;
}
.page2-h1 {
color: blue;
}
This included an unused class (.page2-h1). But when I renamed my class names so that there were no number characters in it and then ran the same command again got the main.css that I expected which contained only:
.pageone-hone {
color: red;
}
This seems to be a known problem too.
Related
How can I save a Cytoscape network as a flat JSON file?
The cytoscape.js examples at cytoscape.org typically store the underlying network data as a flat data.json file (e.g. colas-graph, see also https://js.cytoscape.org/#notation/elements-json).
This is in contrast to the grouped or keyed format obtained when saving a graph as a Cytoscape JSON file (in Cytoscape: file > Export > Network to File > Cytoscape JSON (*.cyjs)).
Note: the documentation indicates that I can use cy.json() to export a JSON representation of the graph, but I am unsure how to call this command (I am relatively new to javascript).
You just have to call the cytoscape object .json() for taking a json object and then download it as you like
here there is an example. I think StackOverflow is blocking downloading file but if you copy and paste this code it should be work
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
style: [{
selector: "node",
style: {
content: "data(id)"
}
},
{
selector: "edge",
style: {
"curve-style": "bezier",
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "a"
}
}, {
data: {
id: "b"
}
}],
edges: [{
data: {
id: "ab",
source: "a",
target: "b"
}
}]
},
layout: {
name: "grid"
}
}));
cy.ready(function() {
const json = cy.json(); // take json from cytoscape
// download json as you want
const data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(json));
const a = document.createElement('a');
a.href = 'data:' + data;
a.download = 'data.json';
a.innerHTML = 'download JSON';
const container = document.getElementById('container');
container.appendChild(a);
});
});
body {
font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
font-size: 14px
}
#cy {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 1;
}
h1 {
opacity: 0.5;
font-size: 1em;
font-weight: bold;
}
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
</head>
<body>
<div id="cy"></div>
<div id="container" style="position:absolute;top:10;left:10;z-index:1"></div>
</body>
In Jenkins, I know I can do this...
pipeline {
agent any
stages {
stage('Demo') {
steps {
MyFunction()
}
}
}
}
void MyFunction() {
sh 'ls /'
}
In this situation, the function is within the pipeline, but then I can always extract MyFunction into a shared library for reuse across pipelines.
But would it be possible to do this with a post-build step?
In this case, I would like to convert this into a function and extract it into a library.
post {
always {
/* clean up our workspace */
deleteDir()
/* clean up tmp directory */
dir("${workspace}#tmp") {
deleteDir()
}
/* clean up script directory */
dir("${workspace}#script") {
deleteDir()
}
dir("${workspace}#2") {
deleteDir()
}
dir("${workspace}#2#tmp") {
deleteDir()
}
}
}
I've tried this
post {
always{
test()
}
}
}
With Function
void test() {
{
/* clean up our workspace */
deleteDir()
/* clean up tmp directory */
dir("${workspace}#tmp") {
deleteDir()
}
/* clean up script directory */
dir("${workspace}#script") {
deleteDir()
}
dir("${workspace}#2") {
deleteDir()
}
dir("${workspace}#2#tmp") {
deleteDir()
}
}
}
But it doesn't seem to work.
Is this possible at all or am I just missing something really obvious?
Passing the name of the workspace as a parameter in the function will solve your issue. The below script works.
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
post{
always{
echo "In : ${env.WORKSPACE}"
test(env.WORKSPACE)
}
}
}
void test(workspace){
echo "In test : " + workspace
deleteDir()
dir("${workspace}#tmp") {
deleteDir()
}
}
Also, instead of calling deleteDir() for multiple tmp directories, if you call deleteDir() only once, then it will delete the workspace as well as tmp directories
The way that works for us to clean up the workspace after a specific stage and without trying to guess the folder name is to make your post function in stage:
pipeline {
agent any
stages {
stage('1') {
steps {
echo 'Hello World'
}
post {
cleanup {
script {
// Workspace Cleanup plugin
cleanWs deleteDirs: true,
notFailBuild: true,
cleanWhenAborted: true,
cleanWhenFailure: true,
cleanWhenSuccess: true
}
}
}
}
}
}
We use WorkspaceCleanup plugin.
I am using type=url in my form to only allow a url to be passed through.
However, using the standard validation message is as follows
Is there a way to change this? Here is the design what I am trying to achive (outline search bar, add message beneath, and make text in search box orange)
Here is function after my form
function searchIt() {
let form = document.querySelector('form')
console.log(form)
form.addEventListener('submit', async(e) => {
// onclick or the event that start the call
interval = setInterval(() => {
progress = progress >= 100 ? 100 : progress + 1
document.getElementById('myprogress').style.width = `${progress}%`
// end interval and wait at 100%
if(progress == 100) clearInterval(interval);
}, maxTime/100)
document.getElementById('loadingcontainer').style.display = ""
e.preventDefault()
let urlIN = form.url.value
let url = encodeURIComponent(urlIN)
console.log(url)
try {
const data = await fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: url
})
}).then(res => {
document.open()
res.text().then(function(text) {
document.write(text)
// Hide the progressbar, stop the timer and reset progress
clearInterval(interval);
progress = 0;
document.getElementById('myprogress').style.width = "0%"
document.getElementById('loadingcontainer').style.display = "none";
});
})
} catch (err) {
console.error(err)
}
})
}
Rather than write all the necessary validation for URLs, you can use the HTML5 input type "url" in place of type "text", which has all that validation built in:
<input type="url" name="location">
That will require a properly formed URL, but ftp:// is also proper.
You can further constrain it by using the
pattern attribute for your requirements "beginning in http://, https://, includes www.".
Here, using novalidate on the <form_> prevents the browser from showing it's own messages, then you can test a field's validity with field.checkValidity()
const urlField = document.getElementById('onlyweb');
const messagebox = document.getElementById('errormessage');
document.getElementById('testform')
.addEventListener('submit', function(e) {
e.preventDefault();
const valid = urlField.checkValidity();
console.log('valid =', valid);
if (valid) {
messagebox.innerHTML = ''; // clear any message that might be there
messagebox.classList.add('hidden');
}
else {
messagebox.innerHTML = '<span class="errmsg">You need to include http:// or https:// and include the "www." prefix.</span>';
messagebox.classList.remove('hidden');
}
});
input:invalid {
border-color: red;
}
div {
margin-bottom: 1em;
}
#errormessage {
font-family: sans-serif;
color: red;
border: 1px solid gray;
padding: 1em;
}
#errormessage.hidden {
display: none;
}
<form id="testform" action="#" novalidate>
<div>
Invalid fields will have a red border
</div>
<div>
<label for="onlyweb">Only Web URLs</label>
<input type="url"
name="onlyweb" id="onlyweb"
pattern="^https?://www\..*$"
>
</div>
<div>
<input type="submit" value="Test It">
</div>
<div id="errormessage" class="hidden">
</div>
</form>
I recommend just manipulating classes and writing CSS using the :valid and :invalid pseudo-selectors, rather than changing a bunch of field.style.something=newvalue which have to be coordinated to make sure you do & undo things consistently.
It also mixes style into your code, instead of keeping it in CSS where it belongs.
See MDN's Client-side form validation
for The Constraint Validation API
especially where it gives "A more detailed example"
Yes, it is perfectly possible. However, you must create the validation yourself by attaching a onsubmit function to the form like so:
var input = document.getElementsByTagName('input')[0];
var expression = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/gi;
var regex = new RegExp(expression);
var errorMsg = document.getElementById("errorMessage");
function val(){
var value = input.value;
if(regex.test(value)){
input.style.borderColor="green";
input.style.color="green";
return true;
}else{
input.style.borderColor="red";
input.style.color="red";
errorMsg.style.display="block";
return false;
}
}
#errorMessage{
color:red;
display:none;
}
.input{
width: 80%;
margin: auto;
}
input{
width: 80%;
margin: auto;
padding: 2em;
border-radius: 25px;
outline: none;
border: 1px solid black;
}
<form action="stackoverflow.com" onsubmit="return val()">
<div class="input">
<input>
<p id="errorMessage">Yikes! That's not a valid URL.</p>
</div>
</form>
You can use the input type url and then check the validity using .checkValidity().From Mozilla on the checkValidity method: checks whether the element has any constraints and whether it satisfies them. If the element fails its constraints, the browser fires a cancelable invalid event at the element, and then returns false.
It's also important to note that when one says URL validation, what exactly do they refer to when referencing a url? One could write in a url address bar, www.stackoverflow.com and they would end up at stackoverflows web site, however, the URL validation will require that the valid protocol http, https is called in the url address in order to validate using an input url type. More info on url can be found here... What is a URL? -Mozilla
const input = document.getElementById("url");
const errorMessage = document.getElementById("errorMessage");
const validate = document.getElementById("validate");
validate.addEventListener('click', (e) => {
e.preventDefault();
if (input.checkValidity() !== true) {
input.className = 'false';
input.classList.remove('true');
errorMessage.style.display = 'block';
} else {
input.className = 'true';
input.classList.remove('false');
errorMessage.style.display = 'none';
}
})
#errorMessage {
display: none;
color: orange;
}
.true {
border: 1px solid green;
color: green;
}
.false {
border: 1px solid orange;
color: orange;
}
input#url {
border-radius: .9rem;
padding: .7rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form novalidate>
<input id="url" type="url" required />
<input type="submit" name="validate" value="Check" id="validate">
</form>
<p id="errorMessage">Yikes! That's not a valid URL.</p>
I am trying to style the using css, but I can't figure out how to make it look like the select box in the link above, but css wont let me change the background color of the options. Any help would be much appreciated.
You could make an active class with the styles you want
eg
.current {
color: green;
.icon {
opacity: 1;
}
}
and then add this class or remove this class based on the current one clicked
const newest = document.querySelector('newestElt')
newest.addEventListener('click', () => {
removeClass();
newest.classList.add('current');
}
function removeClass() {
const navItems = document.getElementsByClassName('navItems');
var navArray = [].slice.call(navItems);
navArray.forEach(item => {
document.querySelector('a').classList.remove('current');
});
}
There is probably a cleaner and shorter solution but this will work
I am trying to extract the json values and put them into a html table.Although i am successful in inserting the data into the table,i couldnot insert them vertical.Below mentioned screenshot explains the problem.
In the table, the values that are being printed in the row are meant to be displayed vertically.i.e they come under the column name.
Attached is the structure of my JSON file.
{
"meta":
{
"view":
{
"columns":[
"cachedContents":{
"name:"name"
}]}}}
more details are available at:
https://data.baltimorecity.gov/api/views/hyq3-8sxr/rows.json
I am trying to print the values that are present in the name column. Below posted is the code.
<html>
<head>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
<style>
#result
{
color:red;
}
</style>
</script>
<script type="text/javascript">
$(document).ready(function()
{
var row = $("<tr/>")
$("#personDataTable").append(row);
$.get("https://data.baltimorecity.gov/api/views/hyq3-
8sxr/rows.json",function(data)
{
$.each(data.meta.view,function(i,obj)
{
if(i=="name")
$("#results").append("<p align='center'>"+obj+"
</p>");
if(i=="description")
$("#results").append("<p align='center'>"+obj+"
</p>");
if(i=="columns")
var length = data.meta.view.columns.length;
for(var ind=0;ind<length;ind++)
{
if(null!=obj[ind].name)
{
$("#results").append("<tr>
<td>"+"name"+obj[ind].name+"</tr></td>");
}
if (null!=obj[ind].cachedContents)
{
$.each(obj[ind].cachedContents,function(j,obj1)
{
if (j=="top")
{
var toplength = obj1.length;
for (k=0;k<toplength;k++)
{
if(null!=obj1[k].item)
{
$("#results").append("<li>"+obj1[k].item+"
</li>");
if(obj[ind].name=="name")
{
row.append($("<td
align='vertical'>" + obj1[k].item + "</td>"));
}
if(null!=obj1[k].item.human_address)
{
$("#results").append("
<li>"+obj1[k].item.human_address+"</li>");
}
}
}
}
}
);
}
}
I am trying to print the values that are present in the name column vertically
Any Suggestions would be highly helpful.