JavaScript global array undefined although it shows in alert - javascript

I have written a JQuery script in SharePoint to truncate a multiple lines of text column. Below is the script:
<script>
window.$divs = [];
window.$i = 0;
window.textFull = new Array();
$(document).ready(function(){
window.setInterval(function(){
/// call your function here
$divs = $("[class^=ExternalClass]");
for($i=0;$i<$divs.length;$i++)
{
textFull[$i] = $($divs[$i]).html();
if(typeof textFull[$i] != 'undefined' && textFull[$i].length > 50)
{
//alert($textFull[$i]); this alert show the correct text
$($divs[$i]).html(textFull[$i].substring(0,49)+"<a href='javascript:alert(textFull[$i]);'>...more</a>");
}
}
}, 500);
});
</script>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
In the above code "javascript:alert(textFull[$i])" shows 'undefined' in alert. But the alert above it shows correct text. Also I when I use a variable instead of an array it works fine in the alert inside anchor tag. I have also declared the array as global. So what am I missing?

You are running into the classic problem using for loop without using a closure to keep track of the index with
No need to create that array if all it is used for is to modify the html
Can do that much simpler using html(fn) and a jQuery event handler
$("[class^=ExternalClass]").html(function(index, oldhtml){
if(oldhtml.length >=50){
// store the full html in element data
$(this).data('html', oldhtml)
return oldhtml.substring(0,49)+"<a class="more-btn">...more</a>"
} else{
return oldhtml
}
}).find('.more-btn').click(function(){
var $div = $(this).parent();
$div.html( $div.data('html'));
});

Related

Copy text from div innerHtml to textarea

A connected question to this problem with the iframe issue:
Copy div from parent website to a textarea in iframe
I'm trying to copy InnerHtml from a div to a TextArea.
I've made two instances of google translator on the same web page, and I'm trying to apply auto-correction of the first instance to the second instance, without changing the first textarea.
I tried different code:
setInterval(function() {
childAnchors1 = document.querySelectorAll("#spelling-correction > a")[0];
$("#source")[1].val(childAnchors1.text());
}, 100);
setInterval(function copyText() {
$(".goog-textarea short_text")[1].val($("#spelling-correction > a")[0].innerText());
}
, 100);
setInterval(function copyText() {
$("#source")[1].val($("#spelling-correction > a")[0].innertext());
}
, 100);
setInterval(function() {
var finalarea = document.getElementsByClassName("goog-textarea short_text")[1];
var correction = document.querySelectorAll("#spelling-correction > a")[0].innerHTML
document.getElementsByClassName("goog-textarea short_text")[1].value = correction.innerText;
}, 100);
onclick='document.getElementsByClassName("goog-textarea short_text")[1].innerHTML=document.getElementById("spelling-correction > a")[0].innerHTML;'
But nothing of that seems to work, unfortunately...
I would be very grateful for any help.
I should have mentioned this. I used iframe to create the second instance, so simple solutions don't work...
This is the code I used for creating iframe instance:
var makediv = document.createElement("secondinstance");
makediv.innerHTML = '<iframe id="iframenaturalID" width="1500" height="300" src="https://translate.google.com"></iframe>';
makediv.setAttribute("id", "iframeID");
var NewTranslator = document.getElementById("secondinstance");
var getRef = document.getElementById("gt-c");
var parentDiv = getRef.parentNode;
parentDiv.insertBefore(makediv, getRef);
I tried to use this to communicate between the iframe and the parent website:
setInterval(function() {
var childAnchors1 = window.parent.document.querySelectorAll("#spelling-correction > a");
var TheiFrameInstance = document.getElementById("iframeID");
TheiFrameInstance.contentWindow.document.querySelectorAll("#source").value = childAnchors1.textContent;
}, 100);
But it doesn't work...
Ok, I made it work with:
var a = document.createElement('iframe');
a.src = "https://translate.google.com";
a.id = "iframenaturalID";
a.width = "1000";
a.height = "500";
document.querySelector('body').appendChild(a)
And
let iframe = document.getElementById("iframenaturalID");
setInterval(function() {
let source = iframe.contentWindow.document.getElementById("source");
let destination = window.parent.document.querySelector("#spelling-correction > a");
source.value = destination.textContent;
}, 100);
Now it does what I tried to do, however I still get mistake message: Uncaught TypeError: Cannot set property 'value' of null
at eval, which points at this line: source.value = destination.textContent;. It's not a big problem though, but still it's strange that it returns this mistake...
Ok, I was able to solve it by adding setTimeout.
Since a textarea is a form element, neither .innerText or .innerHTML will work. You need to extract its content with the value property (or .val() with JQuery).
And FYI:
It's innerText, not .innertext.
.innerText is a property, not a function, so you don't use () after it.
It's .innerHTML, not .innerHtml.
innerHTML is used when there is HTML in the string that should be
parsed as HTML and .textContent is used for strings that should not
be parsed as HTML. Usually, you don't map the contents of one to the
other.
document.querySelectorAll() scans the entire DOM to find all
matching nodes. If you know you only have one matching node or you
only want the first matching node, that's a waste of resources.
Instead, use .querySelector(), which stops searching after the
first match is found.
Since you are using JQuery, you should be consistent in its use. There's no need for .querySelector() or .querySelectorAll() with JQuery, just use JQuery selector syntax.
Here's an example that shows both the vanilla JavaScript and JQuery approaches using the HTML types that you show in your question with the same id values and nesting structure that you show. You can see that I'm using different selectors to correctly locate the input/output elements.
// Standare DOM queries to get standard DOM objects
let source = document.getElementById("source");
let destination = document.querySelector("#spelling-correction > a");
// JQuery syntax to get JQuery objects:
let jSource = $("#source");
let jDestination = $("#spelling-correction > a");
// Vanilla JavaScript way to set up the event handler and do the work
source.addEventListener("keyup", function(){
destination.textContent = source.value;
});
// JQuery way to set up the event handler and do the work
jSource.on("keyup", function(){
jDestination.text(jSource.val());
});
textarea, div {
border:3px solid grey;
width:500px;
height:75px;
font-size:1.5em;
font-family:Arial, Helvetica, sans-serif;
}
.destination { pointer-events:none; background:#e0e0e0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Type in the first textarea</p>
<textarea id="source"></textarea>
<div id="spelling-correction">
Did you mean:
</div>
The problem in all the codes you've tried is how to get the text correctly.
Starting with your First example it should be using innerText instead of text() since it's a jquery object and you're returning a DOM object not a jQuery object:
setInterval(function() {
childAnchors1 = document.querySelectorAll("#spelling-correction > a")[0];
$("#source")[1].val(childAnchors1.innerText);
}, 100);
In your Second example and Third one, you need to remove the parentheses from the innerText like:
setInterval(function copyText() {
$(".goog-textarea short_text")[1].val($("#spelling-correction > a")[0].innerText);
}, 100);
I suggest the use of pure js and textContent attribute like:
setInterval(function() {
var childAnchors1 = document.querySelectorAll("#spelling-correction > a")[0];
document.querySelectorAll("#source")[1].value = childAnchors1.textContent;
}, 100);
NOTE: I should point that your HTML code in invalid since you're using duplicate identifier when the id attribute should be unique in the same document.

Custom Javascript in google tag manager return undefined

in my footer i have a div section structured as follow:
<div id="text_icl-7" class="widget widget_text_icl">
<div class="textwidget">
<p style="text align:justify;">
<img src="image.jpg" alt="YC logo">
Some text
</p>
</div>
</div>
I want capture into a variable the text value, so i write this in gtm:
function () {
var desc = document.getElementById("text_icl-7").childNodes[1];
var p = desc.childNodes[1].childNodes[2];
return p;
}
The problem is that, debugging the page, the variable's value is undefined.
I try the script in another custom page and it works, i write the script in this way:
(function(d) {
var desc = document.getElementById("text_icl-7").childNodes[1];
var p = desc.childNodes[1].childNodes[2];
console.log(p)
})(document)
In console i get the text but not in tag manager, why?? thanks
I can't debug why you're getting undefined values, but I suspect a custom JavaScript variable is not what you need in this instance.
You can return the text contained within a DOM element by using a Google Tag Manager 'DOM Variable'. Configure your variable to use a CSS selector that selects elements that match #text_icl-7 > p. Leaving the 'attribute' field empty will return the text contained with the element by default.
i was helped by gtm forum.
The corret script is:
function() {
var el = document.querySelector('#text_icl-7');
return el && (el.textContent || el.innerText);
}
Now it works, maybe the solution of a dom variable also would works, thanks
Sorry to respond to late this but here is my solution, you need define the variable at the beginning of the script and return it at the end. Example below.
This NOT works:
function(){
document.querySelectorAll('.some-class').forEach(function(item){
var displayStyle = item.style.display;
if (displayStyle === 'block'){
return item.getAttribute('id');
}
})
}
But this works:
function(){
var result = '';
document.querySelectorAll('.some-class').forEach(function(item){
var displayStyle = item.style.display;
if (displayStyle === 'block'){
result = item.getAttribute('id');
}
})
return result;
}

Storing variable via .text() isn't uptodate

I have <span> tags in a div that is removed when user clicks on them. Works fine.
I want to store the .text() inside that div in a variable. The problem is that the updated text doesn't get stored.
Click on a word to remove it in this jsFiddle.
As you can see, the content variable returns the old text, not the new revised one.
How can I store a variable with the updated text?
jQuery:
jQuery(document).ready(function() {
jQuery(document).on("mousedown", ".hello span", function() {
// don't add full stop at the end of sentence if it already ends with
var endChars = [".", "?", "!"];
jQuery(this).fadeOut(function(){
var parentObj = jQuery(this).parent();
jQuery(this).remove();
var text = parentObj.find("span").first().html();
parentObj.find("span").first().html(ta_capitalizeFirstLetter(text));
text = parentObj.find("span").last().html();
if ( endChars.indexOf(text.slice(-1)) == -1 )
{
parentObj.find("span").last().html(text+".");
}
});
var content = jQuery(this).parent().parent().find('.hello').text();
alert(content);
});
});
The code to get the new text should be moved inside the fadeOut callback. Once the animation is completed and element is removed, then the innerText of the parent element will be updated. At this time, the updated content should be read from the DOM.
Demo
// Cache the element
var $el = jQuery(this).parent().parent().find('.hello');
jQuery(this).fadeOut(function () {
jQuery(this).remove();
// Irrelevant code removed from here
...
var content = $el.text();
alert(content);
});
Here's another simple demo with minimal code that'll help to understand the code better.
Demo
I tried to debug your jsfiddle in chrome, and it looks like the priority of your code is like this:
declare on this event - jQuery(this).fadeOut(function(){
get the the current data of the div var content = jQuery(this).parent().parent().find('.hello').text();.
alert your data without changes.
calling the funcntion of fadeout
I think all you have to do is to call your alert and 2 from your anonymous function of fadeout
Just put your alert inside the callback:
jQuery(this).fadeOut(function(){
var parentObj = jQuery(this).parent();
jQuery(this).remove();
var text = parentObj.find("span").first().html();
parentObj.find("span").first().html(ta_capitalizeFirstLetter(text));
text = parentObj.find("span").last().html();
if ( endChars.indexOf(text.slice(-1)) == -1 ) {
parentObj.find("span").last().html(text+".");
var content = parentObj.parent().find('.hello').text();
alert(content);
}
});

Remove innerHTML img completely by jQuery selection

I've dinamically created a div with the code below:
typebox.innerHTML += "<div id='idtypebox' class='typebox'><img id='typeImg' width='30px' height='30px' src="+d[o].src+"></div>";
My intention is to remove completely the innerHTML I created, by changing the innerHTML that had created the img and if change the form A to B, those images will be removed.
function SelectCheck() {
var select_val = $('#Check').val();
// using this to remove typeimg
var toRemove = document.getElementById('typeImg');
toRemove.parentNode.removeChild(toRemove);
if (select_val) {
ajax_json_gallery("Img/"+select_val);
}
return;
}
$(document).ready(function() {
$("#Check").change(SelectCheck).change();
});
I tried this code by on button and it works, but if I put in jQuery selection I get an error
var toRemove = document.getElementById('typeImg');
toRemove.parentNode.removeChild(toRemove);
Why not just :
$("#typeImg").remove();
And the complete code :
function SelectCheck(){
var select_val = $('#Check').val();
// using this to remove typeimg
$("#typeImg").remove();
if(select_val){
ajax_json_gallery("Img/"+select_val);
}
return;
}
jQuery(document).ready(function($) {
myVar=$("#d1 [href]").html();
var href = $(myVar).attr('src');
$("#d1").html('');
$("#d1").html('<img src="'+href+'" class="images_responsive_mode">').removeAttr("href");
});
</script>
this is one of the script which i created for remove the class assigned by wordpress and to assign new class for responsive image , if it useful for you do this !
you can use childNodes to remove the innerHtml
var toRemove = document.getElementById('typeImg');
toRemove.parentNode.removeChild(toRemove.childNodes[0])

use JavaScript to manipulate multiple (predictably) named DIVs

I want to execute a function repeatedly on groups of predictably named html divs.
I am using a drag and drop relationship shown below in which dragging text into a certain div space "target" causes that text to appear in another div called "saves".
<script type="text/javascript">
function OnDragStart (event) {
if (event.dataTransfer) {
var format = "Text";
var textData = event.dataTransfer.getData (format);
}
}
function OnDropTarget (event) {
if (event.dataTransfer) {
var format = "Text";
var textData = event.dataTransfer.getData (format);
if (!textData) {
textData = "<span style='color:red'>The data transfer contains no text data.</span>";
}
var savesDiv = document.getElementById ("saves");
savesDiv.innerHTML = savesDiv.innerHTML + "<br />" + textData;
}
else {
alert ("Your browser does not support the dataTransfer object.");
}
if (event.stopPropagation) {
event.stopPropagation ();
}
else {
event.cancelBubble = true;
}
return false;
}
</script>
The script in combination with the corresponding html works perfectly for the target and saved divs... but what i would really like is to apply the same script to a set of divs pairs named
(target1, saves1 )
(target2, saves2)
(target3,saves3)
(target4 saves4) etc etc
with numbers in div ids going up every time by 1 up to (target20, saves 20) ... Without obviously repeating the same script 20 times with different id names when referring to all the target and saved divs.
I realize this is a total newbie question but I'm really interested to learn the different ways this can be approached.
Give a common class name to these divs so when the dragdrop event occurs, it can be handled using the class name instead of the id; that is, like $('.someClass').someEvent instead of $('#target1'). You can get its id property inside this function using $(this).attr("id").
So if you have "target1" as the id, get the last character ("1") using the JavaScript substring function; you can write generic code such as this:
$('.someClass').someEvent(function(){
var id=$(this).attr(id);
var lastno=id.substring(id.lastIndexOf("t"),id.length);
//now rest of code
$("#saves"+lastno).val($("#target"+lastno).val());
});

Categories