How to zoom a d3 chart correctly?How do JavaScript closures work?How do I check if an element is hidden in jQuery?How do I remove a property from a JavaScript object?How do I redirect to another webpage?How do I correctly clone a JavaScript object?How do I include a JavaScript file in another JavaScript file?How to replace all occurrences of a string?How to check whether a string contains a substring in JavaScript?How do I remove a particular element from an array in JavaScript?How do I return the response from an asynchronous call?
Memory models for assembly libraries for Turbo C
Can a Way of the Open Hand monk's Open Hand Technique prevent Legendary Action reactions?
Why does E7 sharp 9 have a G?
I might blow up!
Why, in the US, are politicians tried by other politicians?
Why would a berry have a slow-acting poison?
Can a Rogue exploit a tiny familiar for automatic Sneak Attack in melee?
Writing critique request: Zhou Ziwang and the revolutionary new technology
Why are Trump's handwritten notes being focused on in the news?
Why Doesn't a Bootable USB Boot
Does this Latin book state that the meaning of the Arabic word ةلم is huc?
Miniseries in post-rapture US with good/evil conflict
"выше" - adverb or an adjective?
Why do HK chefs use a white cloth to clutch wok?
If password expiration is applied, should door-lock expiration be applied too?
Did any of the Space Shuttles land through rain or rainclouds?
Why would a metal file have a cancer warning?
Do I even like doing research?
Can I regain some of my normal hit points while I have a buffer of temporary hit points?
What is the largest piece of space debris volumetrically?
Do gray aliens exist in Star Trek?
Someone said to me, "We basically literally did." What were they trying to express to me?
My advisor wants me to make my PhD thesis weaker
Is it necessary to wipe out vile man-eating dragons?
How to zoom a d3 chart correctly?
How do JavaScript closures work?How do I check if an element is hidden in jQuery?How do I remove a property from a JavaScript object?How do I redirect to another webpage?How do I correctly clone a JavaScript object?How do I include a JavaScript file in another JavaScript file?How to replace all occurrences of a string?How to check whether a string contains a substring in JavaScript?How do I remove a particular element from an array in JavaScript?How do I return the response from an asynchronous call?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
I made a chart with d3 word cloud layout. I want to zoom it using d3.zoom().
The problem is that when I implement the zoom function, the SVG is out of bounds. Like this example: https://codepen.io/bitbyte/pen/oVKGjx
var words = ["two", "two", "seven", "seven", "seven", "seven", "seven", "seven", "seven", "three", "three", "three", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "five", "five", "five", "five", "five", "four", "four", "four", "four", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "one", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "six", "six", "six", "six", "six", "six"]
.map(function(d,i)
//console.log(d);
return text: d, size: -i;
);
var fontName = "Impact",
cWidth = 720,
cHeight = 400,
svg,
wCloud,
bbox,
ctm,
bScale,
bWidth,
bHeight,
bMidX,
bMidY,
bDeltaX,
bDeltaY;
var cTemp = document.createElement('canvas'),
ctx = cTemp.getContext('2d');
ctx.font = "100px " + fontName;
var fRatio = Math.min(cWidth, cHeight) / ctx.measureText(words[0].text).width,
fontScale = d3.scale.linear()
.domain([
d3.min(words, function(d) return d.size; ),
d3.max(words, function(d) return d.size; )
])
//.range([20,120]),
.range([20,100*fRatio/2]), // tbc
fill = d3.scale.category20();
d3.layout.cloud()
.size([cWidth, cHeight])
.words(words)
//.padding(2) // controls
.rotate(function() return ~~(Math.random() * 2) * 90; )
.font(fontName)
.fontSize(function(d) return fontScale(d.size) )
.on("end", draw)
.start();
function draw(words, bounds)
// move and scale cloud bounds to canvas
// bounds = [x0, y0, x1, y1]
bWidth = bounds[1].x - bounds[0].x;
bHeight = bounds[1].y - bounds[0].y;
bMidX = bounds[0].x + bWidth/2;
bMidY = bounds[0].y + bHeight/2;
bDeltaX = cWidth/2 - bounds[0].x + bWidth/2;
bDeltaY = cHeight/2 - bounds[0].y + bHeight/2;
bScale = bounds ? Math.min( cWidth / bWidth, cHeight / bHeight) : 1;
svg = d3.select(".cloud").append("svg")
.attr("width", cWidth)
.attr("height", cHeight)
.call(d3.behavior.zoom().on("zoom", function ()
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
wCloud = svg.append("g")
.attr("transform", "translate(360,200)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) return d.size + "px"; )
.style("font-family", fontName)
.style("fill", function(d, i) return fill(i); )
.attr("text-anchor", "middle")
.transition()
.duration(500)
.attr("transform", function(d)
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
)
.text(function(d) return d.text; );
bbox = wCloud.node(0).getBBox();
;
What is the correct way to make a zoom chart like this https://bl.ocks.org/sgruhier/50990c01fe5b6993e82b8994951e23d0
With the square fixed container with the SVG inside of them and not moving around for all the page when you zoom in it.
javascript d3.js svg zoom bounds
add a comment
|
I made a chart with d3 word cloud layout. I want to zoom it using d3.zoom().
The problem is that when I implement the zoom function, the SVG is out of bounds. Like this example: https://codepen.io/bitbyte/pen/oVKGjx
var words = ["two", "two", "seven", "seven", "seven", "seven", "seven", "seven", "seven", "three", "three", "three", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "five", "five", "five", "five", "five", "four", "four", "four", "four", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "one", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "six", "six", "six", "six", "six", "six"]
.map(function(d,i)
//console.log(d);
return text: d, size: -i;
);
var fontName = "Impact",
cWidth = 720,
cHeight = 400,
svg,
wCloud,
bbox,
ctm,
bScale,
bWidth,
bHeight,
bMidX,
bMidY,
bDeltaX,
bDeltaY;
var cTemp = document.createElement('canvas'),
ctx = cTemp.getContext('2d');
ctx.font = "100px " + fontName;
var fRatio = Math.min(cWidth, cHeight) / ctx.measureText(words[0].text).width,
fontScale = d3.scale.linear()
.domain([
d3.min(words, function(d) return d.size; ),
d3.max(words, function(d) return d.size; )
])
//.range([20,120]),
.range([20,100*fRatio/2]), // tbc
fill = d3.scale.category20();
d3.layout.cloud()
.size([cWidth, cHeight])
.words(words)
//.padding(2) // controls
.rotate(function() return ~~(Math.random() * 2) * 90; )
.font(fontName)
.fontSize(function(d) return fontScale(d.size) )
.on("end", draw)
.start();
function draw(words, bounds)
// move and scale cloud bounds to canvas
// bounds = [x0, y0, x1, y1]
bWidth = bounds[1].x - bounds[0].x;
bHeight = bounds[1].y - bounds[0].y;
bMidX = bounds[0].x + bWidth/2;
bMidY = bounds[0].y + bHeight/2;
bDeltaX = cWidth/2 - bounds[0].x + bWidth/2;
bDeltaY = cHeight/2 - bounds[0].y + bHeight/2;
bScale = bounds ? Math.min( cWidth / bWidth, cHeight / bHeight) : 1;
svg = d3.select(".cloud").append("svg")
.attr("width", cWidth)
.attr("height", cHeight)
.call(d3.behavior.zoom().on("zoom", function ()
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
wCloud = svg.append("g")
.attr("transform", "translate(360,200)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) return d.size + "px"; )
.style("font-family", fontName)
.style("fill", function(d, i) return fill(i); )
.attr("text-anchor", "middle")
.transition()
.duration(500)
.attr("transform", function(d)
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
)
.text(function(d) return d.text; );
bbox = wCloud.node(0).getBBox();
;
What is the correct way to make a zoom chart like this https://bl.ocks.org/sgruhier/50990c01fe5b6993e82b8994951e23d0
With the square fixed container with the SVG inside of them and not moving around for all the page when you zoom in it.
javascript d3.js svg zoom bounds
add a comment
|
I made a chart with d3 word cloud layout. I want to zoom it using d3.zoom().
The problem is that when I implement the zoom function, the SVG is out of bounds. Like this example: https://codepen.io/bitbyte/pen/oVKGjx
var words = ["two", "two", "seven", "seven", "seven", "seven", "seven", "seven", "seven", "three", "three", "three", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "five", "five", "five", "five", "five", "four", "four", "four", "four", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "one", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "six", "six", "six", "six", "six", "six"]
.map(function(d,i)
//console.log(d);
return text: d, size: -i;
);
var fontName = "Impact",
cWidth = 720,
cHeight = 400,
svg,
wCloud,
bbox,
ctm,
bScale,
bWidth,
bHeight,
bMidX,
bMidY,
bDeltaX,
bDeltaY;
var cTemp = document.createElement('canvas'),
ctx = cTemp.getContext('2d');
ctx.font = "100px " + fontName;
var fRatio = Math.min(cWidth, cHeight) / ctx.measureText(words[0].text).width,
fontScale = d3.scale.linear()
.domain([
d3.min(words, function(d) return d.size; ),
d3.max(words, function(d) return d.size; )
])
//.range([20,120]),
.range([20,100*fRatio/2]), // tbc
fill = d3.scale.category20();
d3.layout.cloud()
.size([cWidth, cHeight])
.words(words)
//.padding(2) // controls
.rotate(function() return ~~(Math.random() * 2) * 90; )
.font(fontName)
.fontSize(function(d) return fontScale(d.size) )
.on("end", draw)
.start();
function draw(words, bounds)
// move and scale cloud bounds to canvas
// bounds = [x0, y0, x1, y1]
bWidth = bounds[1].x - bounds[0].x;
bHeight = bounds[1].y - bounds[0].y;
bMidX = bounds[0].x + bWidth/2;
bMidY = bounds[0].y + bHeight/2;
bDeltaX = cWidth/2 - bounds[0].x + bWidth/2;
bDeltaY = cHeight/2 - bounds[0].y + bHeight/2;
bScale = bounds ? Math.min( cWidth / bWidth, cHeight / bHeight) : 1;
svg = d3.select(".cloud").append("svg")
.attr("width", cWidth)
.attr("height", cHeight)
.call(d3.behavior.zoom().on("zoom", function ()
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
wCloud = svg.append("g")
.attr("transform", "translate(360,200)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) return d.size + "px"; )
.style("font-family", fontName)
.style("fill", function(d, i) return fill(i); )
.attr("text-anchor", "middle")
.transition()
.duration(500)
.attr("transform", function(d)
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
)
.text(function(d) return d.text; );
bbox = wCloud.node(0).getBBox();
;
What is the correct way to make a zoom chart like this https://bl.ocks.org/sgruhier/50990c01fe5b6993e82b8994951e23d0
With the square fixed container with the SVG inside of them and not moving around for all the page when you zoom in it.
javascript d3.js svg zoom bounds
I made a chart with d3 word cloud layout. I want to zoom it using d3.zoom().
The problem is that when I implement the zoom function, the SVG is out of bounds. Like this example: https://codepen.io/bitbyte/pen/oVKGjx
var words = ["two", "two", "seven", "seven", "seven", "seven", "seven", "seven", "seven", "three", "three", "three", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "eight", "five", "five", "five", "five", "five", "four", "four", "four", "four", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "nine", "one", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "ten", "six", "six", "six", "six", "six", "six"]
.map(function(d,i)
//console.log(d);
return text: d, size: -i;
);
var fontName = "Impact",
cWidth = 720,
cHeight = 400,
svg,
wCloud,
bbox,
ctm,
bScale,
bWidth,
bHeight,
bMidX,
bMidY,
bDeltaX,
bDeltaY;
var cTemp = document.createElement('canvas'),
ctx = cTemp.getContext('2d');
ctx.font = "100px " + fontName;
var fRatio = Math.min(cWidth, cHeight) / ctx.measureText(words[0].text).width,
fontScale = d3.scale.linear()
.domain([
d3.min(words, function(d) return d.size; ),
d3.max(words, function(d) return d.size; )
])
//.range([20,120]),
.range([20,100*fRatio/2]), // tbc
fill = d3.scale.category20();
d3.layout.cloud()
.size([cWidth, cHeight])
.words(words)
//.padding(2) // controls
.rotate(function() return ~~(Math.random() * 2) * 90; )
.font(fontName)
.fontSize(function(d) return fontScale(d.size) )
.on("end", draw)
.start();
function draw(words, bounds)
// move and scale cloud bounds to canvas
// bounds = [x0, y0, x1, y1]
bWidth = bounds[1].x - bounds[0].x;
bHeight = bounds[1].y - bounds[0].y;
bMidX = bounds[0].x + bWidth/2;
bMidY = bounds[0].y + bHeight/2;
bDeltaX = cWidth/2 - bounds[0].x + bWidth/2;
bDeltaY = cHeight/2 - bounds[0].y + bHeight/2;
bScale = bounds ? Math.min( cWidth / bWidth, cHeight / bHeight) : 1;
svg = d3.select(".cloud").append("svg")
.attr("width", cWidth)
.attr("height", cHeight)
.call(d3.behavior.zoom().on("zoom", function ()
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
wCloud = svg.append("g")
.attr("transform", "translate(360,200)")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) return d.size + "px"; )
.style("font-family", fontName)
.style("fill", function(d, i) return fill(i); )
.attr("text-anchor", "middle")
.transition()
.duration(500)
.attr("transform", function(d)
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
)
.text(function(d) return d.text; );
bbox = wCloud.node(0).getBBox();
;
What is the correct way to make a zoom chart like this https://bl.ocks.org/sgruhier/50990c01fe5b6993e82b8994951e23d0
With the square fixed container with the SVG inside of them and not moving around for all the page when you zoom in it.
javascript d3.js svg zoom bounds
javascript d3.js svg zoom bounds
asked Mar 28 at 22:05
Hctor Aldair Aguilar HernndezHctor Aldair Aguilar Hernndez
876 bronze badges
876 bronze badges
add a comment
|
add a comment
|
1 Answer
1
active
oldest
votes
Here is an updated codepen with your solution: https://codepen.io/cstefanache/pen/ZPgmwy
you have to apply the transformation on an group element not directly on the SVG DOM in order to allow the user have further mouse interaction with the SVG viewport.
.call(d3.behavior.zoom().on("zoom", function ()
groupElement.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
the changes to your original codepen was to store the reference to the word cloud group in order to be used and apply all changes to that reference
wCloud = svg.append("g");
wCloud.selectAll("text")
.data(words)
...
Also the initial transformation was removed because if the group element has a transformation value initially it will be replaced with a new transformation from the d3 event that will have large differences between x,y position and it will generate a flicker on the first transformation.
In order to avoid this the initial position of the group has no transformation but the words were placed relative to the center of the viewport:
.attr("transform", function(d)
return "translate(" + [bMidX + d.x, bMidY + d.y] + ")rotate(" + d.rotate + ")";
)
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55407561%2fhow-to-zoom-a-d3-chart-correctly%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here is an updated codepen with your solution: https://codepen.io/cstefanache/pen/ZPgmwy
you have to apply the transformation on an group element not directly on the SVG DOM in order to allow the user have further mouse interaction with the SVG viewport.
.call(d3.behavior.zoom().on("zoom", function ()
groupElement.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
the changes to your original codepen was to store the reference to the word cloud group in order to be used and apply all changes to that reference
wCloud = svg.append("g");
wCloud.selectAll("text")
.data(words)
...
Also the initial transformation was removed because if the group element has a transformation value initially it will be replaced with a new transformation from the d3 event that will have large differences between x,y position and it will generate a flicker on the first transformation.
In order to avoid this the initial position of the group has no transformation but the words were placed relative to the center of the viewport:
.attr("transform", function(d)
return "translate(" + [bMidX + d.x, bMidY + d.y] + ")rotate(" + d.rotate + ")";
)
add a comment
|
Here is an updated codepen with your solution: https://codepen.io/cstefanache/pen/ZPgmwy
you have to apply the transformation on an group element not directly on the SVG DOM in order to allow the user have further mouse interaction with the SVG viewport.
.call(d3.behavior.zoom().on("zoom", function ()
groupElement.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
the changes to your original codepen was to store the reference to the word cloud group in order to be used and apply all changes to that reference
wCloud = svg.append("g");
wCloud.selectAll("text")
.data(words)
...
Also the initial transformation was removed because if the group element has a transformation value initially it will be replaced with a new transformation from the d3 event that will have large differences between x,y position and it will generate a flicker on the first transformation.
In order to avoid this the initial position of the group has no transformation but the words were placed relative to the center of the viewport:
.attr("transform", function(d)
return "translate(" + [bMidX + d.x, bMidY + d.y] + ")rotate(" + d.rotate + ")";
)
add a comment
|
Here is an updated codepen with your solution: https://codepen.io/cstefanache/pen/ZPgmwy
you have to apply the transformation on an group element not directly on the SVG DOM in order to allow the user have further mouse interaction with the SVG viewport.
.call(d3.behavior.zoom().on("zoom", function ()
groupElement.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
the changes to your original codepen was to store the reference to the word cloud group in order to be used and apply all changes to that reference
wCloud = svg.append("g");
wCloud.selectAll("text")
.data(words)
...
Also the initial transformation was removed because if the group element has a transformation value initially it will be replaced with a new transformation from the d3 event that will have large differences between x,y position and it will generate a flicker on the first transformation.
In order to avoid this the initial position of the group has no transformation but the words were placed relative to the center of the viewport:
.attr("transform", function(d)
return "translate(" + [bMidX + d.x, bMidY + d.y] + ")rotate(" + d.rotate + ")";
)
Here is an updated codepen with your solution: https://codepen.io/cstefanache/pen/ZPgmwy
you have to apply the transformation on an group element not directly on the SVG DOM in order to allow the user have further mouse interaction with the SVG viewport.
.call(d3.behavior.zoom().on("zoom", function ()
groupElement.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
))
the changes to your original codepen was to store the reference to the word cloud group in order to be used and apply all changes to that reference
wCloud = svg.append("g");
wCloud.selectAll("text")
.data(words)
...
Also the initial transformation was removed because if the group element has a transformation value initially it will be replaced with a new transformation from the d3 event that will have large differences between x,y position and it will generate a flicker on the first transformation.
In order to avoid this the initial position of the group has no transformation but the words were placed relative to the center of the viewport:
.attr("transform", function(d)
return "translate(" + [bMidX + d.x, bMidY + d.y] + ")rotate(" + d.rotate + ")";
)
answered Mar 29 at 7:31
Cornel StefanacheCornel Stefanache
5582 silver badges7 bronze badges
5582 silver badges7 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55407561%2fhow-to-zoom-a-d3-chart-correctly%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown