I am using jQuery to append text into a textarea
var box = $('<textarea></textarea>')
.attr({id: 'log_viewer',
readonly: '',
cols: 100,
rows: 40})
.appendTo($(outputEntity));
When data is received from a WebSocket, it's appended to the content of the textarea:
ws.onmessage = function(msg) {
var data = decodeURIComponent(msg.data);
data = data.replace('<', '<');
data = data.replace('>', '>');
box.append(data);
}
What I need is for this box to scroll to the bottom automatically, so that the viewport is always centered on the last page of output. Following some other Stack Overflow suggestions on this topic, I tried:
$('#log_viewer').scrollTop = $('#log_viewer')[0].scrollHeight - $('#log_viewer').height();
However, that doesn't work -- at least, not in Chrome or Firefox on Linux, which is all I have access to. The box doesn't scroll.
How do I make this box auto-scroll to the bottom-most page from JS? Is using append() to add output somehow interfering with the underlying dimension detection mechanisms? Is append() even the right way to go there?
Or perhaps I should use not use a textarea at all, but rather a DIV with a scroll bar? Admittedly, I'm rather behind the times on HTML + CSS and don't know exactly how to best accomplish that and still get the monospace-formatted, wrapped output I'm after.
Thanks much for any suggestions!
SOLVED:
http://jsfiddle.net/Ua9qc/
var h1 = $('#log_viewer')[0].scrollHeight,
h2 = $('#log_viewer').height();
$('#log_viewer').scrollTop(h1 - h2);`
I am not sure this will help you. If you wanna scroll certain element at the bottom, you can use this function to scroll by passing div id. Add these function to script
function scrollme(id)
{
var scrollElem = scrollableElement('html', 'body');
var targetOffset = $(id).offset().top;
$(scrollElem).animate({scrollTop: targetOffset-100}, 1000, function() {
});
}
function scrollableElement(els)
{
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
Related
I am using IE11 for this since that is my companys standard browser.
I am working on a solution to catch the paste event when pasting a screen dump into the web application. So far so good but after I have pasted the image I would like to change the size. Preferable before actually so I don't get a jumping application.
I have create a jsfiddle where you can see the entire test application: http://jsfiddle.net/e5f5gLan/3/
Do like this when running the jsfiddle:
Make a screen shot
Put the marker in the red square
Press Ctrl + v
Now the intention is that the pasted image should become 100px x 100px in size. It doesn't.
The problem is that I am not getting hold of the DOM object so I can set the style/size of the image.
The significant part is at the end of the javascript (I guess...):
var image_container = document.getElementById('pastearea');
var image = image_container.getElementsByTagName("img");
image[0].setAttribute("style", "width: 100px; height: 100px");
First of all, I imagined that the img element would become part of an array and that I should access the only img-element using image[0]. But then I get the error "Not possible to get setAttribute for a reference that is undefined or null. " (freely translated from Swedish...)
Ok, perhaps it understands it is only one element and just returns an object that isn't an array. So I changed the last row above to:
image.setAttribute("style", "width: 100px; height: 100px");
Then I get that setAttribute is not supported by the object.
If I create an HTML page with similar structure (img inside div) and just tries to change the size, then it works. Check out this one (click the button to shrink the image): http://jsfiddle.net/m4kzd7jp/3/
How can I change change the size of the image before or after I have pasted it?
Yeah I added the style and it worked to keep it 100px height/width.
#pastearea img { width: 100px; height: 100px; }
I tested your code and the filelist was always 0. If you want to handle this through code, here's what I was using in our project. basically you should be looping items not files and checking if it is a file.
function (e) {
var clip = e.clipboardData || window.clipboardData;
if (clip) {
var preInsert = getData(); // this pulled the input box text or div html
for (var i = 0; i < clip.items.length; i++) {
var item = clip.items[i];
if (item.kind == "file" &&
item.type.indexOf('image/') !== -1) {
var fr = new FileReader();
fr.onloadend = function () {
if (preInsert == getData()) // if nothing changed, we'll handle it otherwise it was already handled
setData(fr.result);
};
var data = item.getAsFile();
fr.readAsDataURL(data);
}
}
}
}
This area shows what I was doing in angular to get/set
var getSelection = function() {
if (window.getSelection && window.getSelection().rangeCount > 0) //FF,Chrome,Opera,Safari,IE9+
{
return window.getSelection().getRangeAt(0).cloneRange();
}
else if (document.selection)//IE 8 and lower
{
return document.selection.createRange();
}
return null;
}
var isInputTextarea = false; // I was being more generic in my angular directive
var getData = function () {
if (isInputTextarea)
return $element.val();
return $element.html();
};
var setData = function (src) {
if (isInputTextarea) {
$element.val(function (index, value) {
return value + " " + "<img src='" + src + "'>";
});
}
else {
var selection = getSelection(); // I presume we have focus at this point, since it is a paste event
if (selection) {
var img = document.createElement("img");
img.src = src;
selection.insertNode(img);
}
}
};
I am inserting a textarea to a side bar (exactly on the right to), wherever a click is made on the page. The code is:
$('#page_to_be_clicked').click(function(e){
var offset = $(this).offset();
var comment_box_y_coord = e.pageY - offset.top;
alert(comment_box_y_coord);
$("#sidebar").append('<textarea id="cmmnt" rows="4" cols="10" '+
'style="position:absolute;top:'+comment_box_y_coord +
'px;left:5px"></textarea>');
})
The problem with this is that, if a textarea is already present at the location, it will overlap the existing, i.e. if a click is made twice at the same point on the page, then two textareas are created on top of each other. Instead, it should be created one below the other.
Is there a way to check, if a child already exists at the required co-ordinates?
Any help will be appreciated. Thanks.
How exactly should the textareas appear on clicks in a sequence:
This needs to be tested properly, but I think you need to do this:
DEMO
In your function change this line:
var comment_box_y_coord = checkCoords(e.pageY - offset.top);
and then add this function:
function checkCoords(y) {
if ($("textarea").length>0) {
$ts = $("textarea");
for (var i = 0; i<$ts.length;i++) {
var $ti = $ts.eq(i),
tcoords = [$ti.offset().top, $ti.offset().top+$ti.height()]
if (y>=tcoords[0] && y <= tcoords[1]) {
y = tcoords[1]+3;
}
}
}
return y;
}
Well, one more question. Since I started learning javascript short time ago, I am almost obsessed trying new things! Here it goes:
Let's say that I have an array of strings and I want to iterate on it with a navigation menu with the buttons FIRST, PREVIOUS, NEXT, LAST.
Look at this code:
var thearray = ["article1", "article2", "article3"];
var thebody = document.getElementsByTagName('body')[0];
var divcontainer = document.createElement("div");
var divpage = document.createElement("div");
function generatepage(article) {
var paragraph = document.createElement("p");
var name = document.createTextNode(thearray[article]);
paragraph.appendChild(name);
divpage.appendChild(paragraph);
}
divcontainer.appendChild(divpage);
thebody.appendChild(divcontainer);
generatepage(0); // that would be for the first article
I also figured out that generatepage(thearray.length -1)would be the call for the last article, so I have solved two buttons (before generating new content I would erase it with innerHTMLbut what I cannot think about how to do are the PREVIOUS and NEXT buttons...
Do you have any suggestion about how should I get started to make working PREVIOUS and NEXT?
I attach a JSFiddle
Thank you so much for any advice!
You can save the active page in a variable outside the function:
var page = 0;
Then you don’t need to bring any page into generatepage():
function generatepage() {
var paragraph = document.createElement("p");
var name = document.createTextNode(thearray[page]);
paragraph.appendChild(name);
divpage.appendChild(paragraph);
}
Now you can control the page from outside the function:
var next = function() {
if ( page < page.length-1 ) { page++; }
}
var prev = function() {
if ( page ) { page--; }
}
So to show the first page:
page = 0;
generatepage()
And the next:
next();
generatepage()
etc.... There are other ways too of course but this might give you an idea.
You can save a variable outside the scope of the function to memorize the current article
when you add Eventlisteners to the buttons you can call the next and previous item
but you should somehow replace the content of the div with the next one instead of appending it (i don't know a thing about manipulating dom elements)
you could try something like this:
var thearray = ["article1", "article2", "article3"];
var thebody = document.getElementsByTagName('body')[0];
var divcontainer = document.createElement("div");
var divpage = document.createElement("div");
var currentarticle
function generatepage(article) {
if(thearray[article]) {
currentarticle = article
var paragraph = document.createElement("p");
var name = document.createTextNode(thearray[article]);
paragraph.appendChild(name);
divpage.innerHTML= paragraph.innerHTML
}else {
return false
}
}
divcontainer.appendChild(divpage);
thebody.appendChild(divcontainer);
generatepage(0); // that would be for the first article
document.getElementById("next").addEventListener("click",function() {
generatepage(currentarticle + 1)
});
document.getElementById("previous").addEventListener("click",function() {
generatepage(currentarticle - 1)
});
document.getElementById("last").addEventListener("click",function() {
generatepage(thearray.length - 1)
});
document.getElementById("first").addEventListener("click",function() {
generatepage(0)
});
heres the Fiddle
Is there any specific function for scrolling up and scrolling down in the TextArea. "onscroll" triggers when scrolling up/down happens in the TextArea.
Also, how to go to the new line after the last line in the text area and put "dash"(--) when clicking(scrolling) down. Thanks.
I might be wrong but as I understand it you're after a function that actually programmatically scrolls the textarea for you. If this is correct the following works:
var scrollUp = function(elementId) {
"use strict";
var element = document.getElementById(elementId);
element.scrollTop = 0;
};
var scrollDown = function(elementId) {
"use strict";
var element = document.getElementById(elementId);
element.scrollTop = element.scrollHeight;
};
See jsFiddle example here: http://jsfiddle.net/WnHpj/3/
You can of course use scrollTop to move the scroll in smaller increments if that is what you wish.
I don't really understand what you are looking for with your last question, please explain further if you still want help with that.
EDIT
The dashes... add this function:
var addDashes = function(elementId) {
"use strict";
var element = document.getElementById(elementId);
if(element.value.substring(element.value.length - 4, element.value.length) !== "\n--\n") {
element.value = element.value + "\n--\n";
element.focus();
}
};
See the updated jsFiddle example: http://jsfiddle.net/sQVe/WnHpj/7/
Hope that is what you wanted.
$("#textbox").scroll(function(e){
//this happens when there is a scrolling action in your element
})
I have the following function:
function slideDown() {
//get the element to slide
sliding = document.getElementById('slideDiv1');
//add 1px to the height each time
sliding.style.height = parseInt(sliding.style.height)+1+'px';
t = setTimeout(slideDown,30);
if (sliding.style.height == "401px") {
clearTimeout(t);
}
}
which is called within this function:
function addDiv(nextImageSlide) {
//finds the src attribute of the image nested in the Li
elemChild = nextImageSlide.firstChild;
imageSrc = elemChild.getAttribute('src');
//loops and creates six divs which will be the slices. adds background property etc
for (i = 0, j = 0, k = 1; i< = 19; i++, j++, k++) {
var newDiv = document.createElement('div');
newDiv.setAttribute('class', 'new-div');
newDiv.id='slideDiv' + k;
newDiv.style.height = '1px';
newDiv.style.background = 'url(' + imageSrc +') scroll no-repeat - '+39.5 * j + 'px 0';
var a = document.getElementById('content');
a.appendChild(newDiv);
}
slideDown();
}
Which is called within another function that defines nextImageSlide. It later removes all the divs that it just made.
The idea is for an image gallery. When the user hits the next button, I want slices of the next image to slide down to show the next image. Those slices are then taken away and the new image revealed.
I would like something like this: http://workshop.rs/projects/jqfancytransitions/.
It's for an assignment so we have to write all the code ourself and this is the best way I can think to replicate it. The only problem is that I keep getting an error:
'sliding is null. sliding.style.height = parseInt(sliding.style.height)+1+'px';'
No matter what I do I can't get rid of it. The thing is if I define sliding as a totally different id, (for example I made a random little div outside of everything), it working.
This error shows when I try to access the divs, it just made that it throws a hissy fit.
Anyone see any errors in my code?
Hopefully this is just a typo while pasting into the site here, but:
car a = document.getElementById('content');
^---syntax error, which'll kill your entire script - var?