Embed cells in Site + SAGE - sage

I like use the SAGE to embed any code (example below). But I want linked two cells using this instruction but this not work. How I will be able to fix this?.
For example I trying call from "compute" cell the function Hola() in the cell "mycell".
<script>
$(function () {
// Make the div with id 'mycell' a Sage cell
sagecell.makeSagecell({inputLocation: '#mycell',
evalButtonText: 'Evaluate'});
// Make *any* div with class 'compute' a Sage cell
sagecell.makeSagecell({inputLocation: 'div.compute',
linked: true,
evalButtonText: 'Evaluate'});
});
</script>
<div id="mycell">
<script type="text/x-sage">
def Hola():
print "Hola"
</script>
</div>
<div class="compute"><script type="text/x-sage">
Hola()
</script>
</div>

Your problem is that you have two different types. The linked:true will only work inside of each makeSagecell call div type, if I'm not mistaken. I haven't tried anything else, but it seems reasonable that your example would not work - and linked:true definitely does work with all within the same class, or my lecture notes for today wouldn't work!
Edit: Here's what I do, or at least an example. This seems to work fine.
$(function () {
// Make *any* div with class 'compute' a Sage cell
sagecell.makeSagecell({inputLocation: 'div.compute',
evalButtonText: 'Evaluate',
linked:true});
});
[snip]
<div class="compute"><script type="text/x-sage">
def r2(n):
n = prime_to_m_part(n,2)
F = factor(n)
ret = 4
for a,b in F:
if a%4==3:
if b%2==1:
return 0
else:
n = prime_to_m_part(n,a)
else:
ret = ret * (b+1)
return ret
def L(n):
ls = []
out = 0
for i in range(1,n+1):
out += r2(i)
ls.append((i,out/i))
return ls
</script></div>
<div class="compute"><script type="text/x-sage">
#interact
def _(n=100):
P = line(L(n))
P += plot(pi+pi*sqrt(2)/sqrt(x),x,3,n,color='red')
P += plot(pi-pi*sqrt(2)/sqrt(x),x,3,n,color='red')
P += plot(pi,x,3,n,color='red',linestyle='--')
show(P)
</script></div>
I would also ask on ask.sagemath.org if you continue to have trouble.

Related

RStudio Visual editor - data.frame preview too narrow, does not resize

I'm trying to use the RStudio Visual Editor more for Quarto notebooks.
I really like it, but I there's an issue that makes it unusable: when I print a data.frame from a chunk, it gets printed in a very narrow rectangle that does not scale up (as it would with the normal source editor).
This makes it unusable because often I can't see the full variable names or the full values.
I tried looking at the options (Global Options > R Markdown > Visual) but I can't find anything that changes this: Editor content width only changes the width of the text and code, not the chunk output.
Coercing a data.frame to tibble also doesn't fix this.
I'm using RStudio 2022.07.2 Build 576.
Alright I know I answered this question before. I can't find that question or my answer in Stack Overflow, but I found the script I used to create & test the answer. I tested it because I think it was a few years ago. Everything seems to work.
This isn't a permanent solution. It will persist until you restart RStudio.
Step 1: Right-click anywhere in RStudio and select 'Inspect Element' from the dropdown to open developer tools. If you weren't aware, it's just like a browser that way.
Step 2: You need to use the console. Whether you use the console drawer (three dots) or the console tab (top of the inspector window, second from the left).
The first JS function
At the cursor, you'll paste two javascript functions. I store these in an RMD, within a JS chunk. They won't do anything when you knit.
allOf = document.querySelectorAll('[data-ordinal]'); //find them all
if (allOf==undefined || allOf==null) {
allOf = document.querySelector('[data-ordinal]'); // if there is only one
}
sAdd = "max-width: none;" // create style to add
try{
for(i = 0, n = allOf.length; i < n; i++){ //loop through them all
styler = allOf[i].getAttribute("style");
if (styler==undefined || styler==null) { // if there are no HTML styles set
styler = "";
console.log("No style attributes found for ", i);
}
if (styler!="width: 100%; max-width: 800px;") {// if this isn't a chunk output as expected
continue;
console.log("Attributes not changed for ", i);
}
allOf[i].setAttribute("style",styler+sAdd);
console.log("Attributes set for ", i);
}} catch(error) {
console.error(error);
}
The second JS function
allMore = document.querySelectorAll('.ace_lineWidgetContainer > div'); // first child of class
if (allMore==undefined || allMore==null) {
allMore = document.querySelector('.ace_lineWidgetContainer > div'); // if there is only one
}
sAdd2 = "overflow: visible;" // create style to add
try{
for(j = 0, m = allMore.length; j < m; j++){ //loop through them all
styler2 = allMore[j].getAttribute("style");
if (styler2==undefined || styler2==null) { // if there are no HTML styles set
styler2 = "";
console.log("No styles were found for ", j)
}
allMore[j].setAttribute("style",styler2+sAdd2); // append new styles
allMore[j].style.height = null; // remove the height style
console.log("Attributes set for ", j);
}} catch(error) {
console.error(error);
}
The console after entering the functions.
The inline rendered chunks before and after side by side

How to automatically generate a range of buttons with pre-determined onclick events?

I am trying to generate a button from a range X; in this case, from 0 to 25, and when I click in one generate button, it will alert the word eggs. I followed the rules to generate an on click event on an element through JavaScript, but the code didn't work. What is wrong with the code?
The code is in the link. Unfortunately, I couldn't upload it through CTRL+K stackoverflow feature.
https://textuploader.com/1gynb
Hei,
Not a javascript expert but I think this does what you want:
<p id='ai'>Click the button to make a BUTTON element with text.</p>
<button onclick="generator()">Try it</button>
<script>
function generator() {
for (var x = 0; x < 26; x++) {
var btn = document.createElement("BUTTON");
btn.innerHTML = x;
btn.setAttribute("onclick", "myFunction();");
document.getElementById('ai').innerHTML += btn.outerHTML;
}
}
function myFunction() {
console.log("done")
}
</script>

Angular read more button based on NUMBER OF LINES not number of letters

What I need is an Angular or CSS solution which will add a "read more" button if the text is more than 5 lines long.
I have an Angular page which displays text, which has a letter limit of 150 characters.
{{post.post_text | limitTo:letterLimit}}
But in some instances the posts are too long, because they have been written with many many line breaks ie :
my post
line 2
line 3
l
i
n
e
...still less than 150 chars, but it begins to break my page.
So I need is an Angular or CSS solution which will add a "read more" button if the text is more than 5 lines long.
Forgive me, but this is my first attempt at Angular, I don't know where to start! Any help would be much appreciated.
so far
I have only found answers and tutorials which relate to number of characters. I really need a solution based on number of lines or total line-height. Thanks.
You can try such a filter:
{{post.post_text | limitTo:letterLimit | maxLines: linesLimit}} // toggle lines limit with the show more
app.filter('maxLines', function() {
return function(txt, limit) {
var parts = txt.split("\n");
if(limit == 0) return parts.join('<br/>');
return parts.slice(0,limit).join('<br/>');
}
})
In view:
<button class="show-more" ng-if="checkLines(checkLines(resource.description)"></button>
In Controller:
$scope.lines_limit_default = 3;// ex.
function checkLines(txt) {
if(txt && txt != null) {
return (txt.split("\n").length > $scope.lines_limit_default) ? true : false;
} else return false;
};

How to flow a working clock into text?

I am trying to place a live clock into a body of text. I need it to flow as if it were just part of the text, but still be live to the local device. Playing around in Adobe Muse I have been able to get a clock into the text, but it segregates itself to its own line rather than flowing like part of the paragraph.
Following is the code Muse produced. I assume I need to make a change to either actAsInlineDiv normal_text, or actAsDiv excludeFromNormalFlow, or both, but how?
<p id="u3202-10"><span class="Character-Style">You look at the clock on this device and it reads </span><span class="Character-Style"><span class="actAsInlineDiv normal_text" id="u13390"><!-- content --><span class="actAsDiv excludeFromNormalFlow" id="u13388"><!-- custom html --><html>
<head>
<script type="text/javascript">
function startTime()
{
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
// add a zero in front of numbers<10
m=checkTime(m);
document.getElementById('txt').innerHTML=h+":"+m;
t=setTimeout('startTime()',500);
}
function checkTime(i)
{
if (i<10)
{
i="0" + i;
}
return i;
}
</script>
</head>
<body onload="startTime()">
<div id="txt"></div>
</body>
</html>
</span></span></span><span class="Character-Style">As a result you believe that this is the time. As it happens this is the time but unknown to you your device's clock has stopped functioning and is stuck. Does your true belief that this is the time count as knowledge?</span></p>
I don't know about Muse, but if all you want is a clock of the current time running inline with some text you could do this:
window.onload = displayTime;
function displayTime() {
var element = document.getElementById("clock");
var now = new Date();
var options = {hour: '2-digit', minute:'2-digit'};
element.innerHTML = now.toLocaleTimeString(navigator.language, options);
setTimeout(displayTime, 1000);
}
The current time is <span id="clock"></span> and it's inline with text.
EDIT
I added these two lines to remove the seconds from display as you requested in your comment.
var options = {hour: '2-digit', minute:'2-digit'};
element.innerHTML = now.toLocaleTimeString(navigator.language, options);

Add classes to adjacent elements dynamically on mouseenter

I'm creating a grid of elements and have a hover effect in place, using CSS transitions, for each element. I'd like to add secondary effects on adjacent x- and y-axis elements as well, creating a cloud effect. I imagine I'll be referencing those elements using jQuery's next() and prev() methods, or by $index and $parent.$index.
The grid area will be large enough to prevent row-wrapping (using negative margins and hidden overflow).
Here's a simplified example of my repeat:
<div class="activity-thumb-row" ng-repeat="i in getNumArray(20) track by $index">
<div class="activity-thumb"
ng-class="{'adjacent': adjacent}"
ng-repeat="j in getNumArray(30) track by $index"
ng-mouseenter="highlightActivities()">
</div>
</div>
And a function in the controller (which I realize may not be the best approach):
$scope.highlightActivities = function() {
$(this).next().adjacent = true;
$(this).prev().adjacent = true;
}
How can I target elements adjacent to the hovered element using ng-class (or something else) inside ng-repeat?
Here's a fiddle for fiddling.
For reference, here are some related discussions:
Change class on mouseover in directive
Angular js ng repeat with conditional ng class not applying css class
ng-mouseover and leave to toggle item using mouse in angularjs
Here's a directive that calculates all of the indices of adjacent cells and adds the adjacent class using jQuery only ... not ng-class.
Assumes that rows will wrap , would need adjusting for individual row elements
.directive('activityThumb', function() {
return {
restrict: 'C',
link: function(scope, elem) {
elem.bind('mouseenter', function(e) {
var elW = elem.width(),
$parent =elem.parent(),
parentW = $parent.width(),
$items = $parent.children(),
numItems =$items.length
itemsPerRow = Math.floor(parentW / elW),
idx = elem.index(),
rowIndex = idx % itemsPerRow;
/* object of various indices , easy to inspect*/
var adjacentIdx = {
top: idx > itemsPerRow ? idx - itemsPerRow : false,
right: rowIndex != itemsPerRow ? idx + 1 : false,
left: rowIndex > 0 ? idx - 1 : false,
bottom: (numItems - idx) > itemsPerRow ? idx + itemsPerRow : false
}
console.dir(adjacentIdx);
$items.removeClass('adjacent')
$.each(adjacentIdx, function(position, index){
if(index !== false){
$items.eq(index).addClass('adjacent');
}
});
});
}
}
});
It wouldn't take much tweaking to remove jQuery dependency either.
Also would need additional directive on parent to remove extra classes when mouse leaves the main parent from one of the edges
DEMO
First, it's not a good idea to deal with DOM elements in the controller.
Also, this problem seems to be mostly styling related, and not functionality related. I would thus try to keep the logic in the View and not in the controller.
There are 2 ways to deal with View-specific logic: 1) using custom directives or 2) View-defined scope variables
The second approach can work here and seems like the cheapest approach, but also a bit ugly. It ng-inits the rowHighlight array in the scope and sets which element is highlighted:
<div ng-repeat="i in getNumArray(20) track by $index" ng-init="rowHighlight = []">
<div class="activity-thumb"
ng-repeat="j in getNumArray(30) track by $index"
ng-class="{'adjacent': rowHighlight[$index-1] || rowHighlight[$index+1]}"
ng-mouseenter="rowHighlight[$index] = true"
ng-mouseleave="rowHighlight[$index] = false">
</div>
</div>
updated fiddle

Resources