Getting correct div class text without reloading page - javascript

I quickly put together a small piece of code to fetch and modify a string from a class on a webpage (chrome extension).
The code works Fine on the first runtime, but if I navigate the webpage to a new company where the class text is changing, the code stops to work correctly (it returns the values from the first runtime)
If I refresh the page or open it up in a new tab it works fine again.
I am 100% new to javascript, I have no clue how to fix this.
Sidenote: Is there a way for me to ask the user a boolean question on runtime, and depending on the answer return either the partname or the finalpart string to the clipboard?
// content.js
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.message === "clicked_browser_action") {
var wholeName = document.getElementsByClassName('ng-binding ng-scope')[0].innerHTML;
var partName = wholeName.substring(0, 4)
var finalPart = "m" + partName.substring(0, 1) + "a" + partName.substring(2, 1) + "x" + partName.substring(3, 2) + "X" + partName.substring(3, 4)
copyStringToClipboard(finalPart);
}
}
);
function copyStringToClipboard(str) {
// Create new element
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = str;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = { position: 'absolute', left: '-9999px' };
document.body.appendChild(el);
// Select text inside element
el.select();
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
}

Related

How to add element attribute JQuery Webview Android?

I want to inject some script after the page is loaded, but the script is not injected or maybe i write it wrong. And here is the code that I want to inject.
val script = "javascript:(function() { $('.numberonly').attr('inputmode','numeric');}())"
and onPageLoaded
binding.webview.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
isLoaded = true
Utility.dismissProgressDialog()
view.evaluateJavascript(script) {
Log.e("script", "onPageFinished: $it")
}
}
}
This is an example that I'm trying to add some attribute to an element, and I try this to text input. Does the script is correct to change an attribute, or what should I do without changing the Web Code directly?
Update
I try to add attributes by element ID, It can be added.
But when I try adding to the class, it's not added.
Here is the code
val script = "javascript: " +
"var berninis = document.querySelectorAll('.numberonly');" +
"for(var i = 0; i < berninis.length; i++) {" +
"berninis[i].setAttribute(\"inputmode\", \"numeric\");" +
"}"
and this is the code when I try using element ID
val script = "javascript:document.getElementById('form_userid').setAttribute(\"inputmode\", \"numeric\");"

JavaScript Clipboard app not working, need assistance

<!DOCTYPE html>
<head>
<title> Query to Clipboard JS Applet by Damien Lesser </title>
</head>
<body>
<script type='text/javascript'>
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
if getQueryVariable('list') === null{
var clip = getQueryVariable('clip')
} else{
//Nothing
};
function copyStringToClipboard (str) {
// Create new element
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = clip;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
// Select text inside element
el.select();
el.setSelectionRange(0, 99999); /* For mobile devices */
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
};
copyStringToClipboard(clip);
var alert1 = 'copied '
var alert2 = ' to clipboard successfully'
console.log(alert1.concat(clip.concat(alert2)));
var para = document.createElement('p');
para.innerHTML = 'Copied successfully!'
</script>
</body>
</html>
As you have probably guessed, I am new to JavaScript, and I am trying to make a tool that allows developers to open a url with a query string, for the query to then be used for the clipboard, in those few niche cases where you can’t use other methods, or don’t have enough experience. It is supposed to happen automatically, but it produces no results.
If you would like to test it out, or use this tool once I have completed development, just go to https://querytoclip.netlify.app/
and then add ‘?clip=’ (without quotes)
Beyond what I have asked for so far, it would be nice if someone could make my code more efficient, because I am no wizard...
This may help you a little:
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return (false);
}
if (getQueryVariable('list') === null) {
var clip = getQueryVariable('clip')
} else {
//Nothing
};
function copyStringToClipboard(str) {
// Create new element
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = clip;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = {
position: 'absolute',
left: '-9999px'
};
document.body.appendChild(el);
// Select text inside element
el.select();
el.setSelectionRange(0, 99999); /* For mobile devices */
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
};
copyStringToClipboard(clip);
const contentDiv = document.getElementById("content");
var paragraph = document.createElement('p');
const paragraphContent = document.createTextNode("Copied successfully!");
paragraph.appendChild(paragraphContent);
document.body.insertBefore(paragraph, contentDiv);
Your code has a number of issues, but beyond that, you are going to run into some issues trying to copy to the clipboard on page load.
For security reasons, many document.execCommand commands require a user interaction (like clicking on a button). Copy is one such method. You could add a button to the page, and use #CLiown response to get something working where the page opens and you click a quick "copy" button.
For more info, read:
https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

Pressing Enter is creating the Tag but keeping the Text in Select2

Select2 Version: 4.0.5
Problem:
In a multitag (with tags: true or with pre-filled tags) everytime when i hit enter to select the tag, it creates the tag but keeps the text right on side of the new tag, it just disappear if I press another key after. (Happens only with Enter key)
Example:
As you can see, when I type a tag and press Enter, it creates the tag (the expected behavior) but, it keeps the original text in the right side of the new tag...
Is it a normal behavior? Or what should I do?
My Select2 Code:
var editorTagElement = document.createElement("select");
editorTagElement.className('myEditor');
editorTagElement.setAttribute("multiple", "multiple");
editorTagElement.style.overflow = 'auto';
editorTagElement.style.fontSize = '13px';
this.OptionsSelect2 = {};
this.OptionsSelect2.placeholder = "";
this.OptionsSelect2.language = ReturnCustomLanguage();
this.OptionsSelect2.formatNoMatches = function () {
return '';
};
this.OptionsSelect2.allowClear = true;
this.OptionsSelect2.minimumInputLength = 2;
this.OptionsSelect2.tags = true;
this.OptionsSelect2.tokenSeparators = [' '];
this.OptionsSelect2.createTag = function (params) {
var term = $.trim(params.term);
if (term.length < 2) {
return null;
}
term = term.replace(/ /g, "");
return {
id: term,
text: term,
newTag: true
}
};
this.OptionsSelect2.closeOnSelect = false;
$('.myEditor').select2(this.OptionsSelect2);
After this, I append the editor to body or to another place in my html...
Option closeOnSelect is keeping the value, while it's not an expected behaviour.
If you will change closeOnSelect to true (default value, just remove this.OptionsSelect2.closeOnSelect = false; in your code) it will work as you expect.
To keep popup open after adding a value, you should write a handler similar to suggested in the github issue

How to force update HTML's TextArea element?

Sorry for newbie question but it's related to WebKit issue. I have the next JS code:
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&");
//text = text.replace(/</g, "<");
//text = text.replace(/>/g, ">");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
console.log('updated element.value');
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})
element is textarea element:
<textarea id="output" rows="8"></textarea>
I have code that printf using that function and then shows prompt to type user name.
So i expect to see 'updated element.value' in browser console and printed text in textarea before prompt dialog is shown.
How can i force textarea to refresh after it's changed (element.value += text + "\n")?
It works as expected in chrome/firefox but fails in Safari(WebKit) - i can't see output at the moment prompt dialog is shown.
To me it sounds like something that can't be done, but there might be Webkit specific hacks I'm not aware about. Maybe all browsers do both updates during the same render cycle which you'd expect, but Safari displays the prompt first and somehow pauses the remaining updates until the prompt is dismissed.
The most obvious workaround is something like
print('lorem ipsum');
setTimeout(function(){
var response = prompt('my question here');
//handle the response
}, 10);
which is likely to guarantee that the textarea update happens before the prompt locks things.

Chrome Extension doesn't considers optionvalue until reloaded

I'm working on my first Chrome Extension. After learning some interesting notions about jquery i've moved to raw javascript code thanks to "Rob W".
Actually the extension do an XMLHttpRequest to a remote page with some parameters and, after manipulating the result, render an html list into the popup window.
Now everything is up and running so i'm moving to add some option.
The first one was "how many elements you want to load" to set a limit to the element of the list.
I'm using fancy-setting to manage my options and here's the problem.
The extension act like there's a "cache" about the local storage settings.
If i do not set anything and perform a clean installation of the extension, the default number of element is loaded correctly.
If i change the value. I need to reload the extension to see the change.
Only if a remove the setting i see the extension work as intended immediately.
Now, i'm going a little more into specific information.
This is the popup.js script:
chrome.extension.sendRequest({action: 'gpmeGetOptions'}, function(theOptions) {
//Load the limit for topic shown
console.log('NGI-LH -> Received NGI "max_topic_shown" setting ('+theOptions.max_topic_shown+')');
//Initializing the async connection
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gaming.ngi.it/subscription.php?do=viewsubscription&pp='+theOptions.max_topic_shown+'&folderid=all&sort=lastpost&order=desc');
xhr.onload = function() {
var html = "<ul>";
var doc = xhr.response;
var TDs = doc.querySelectorAll('td[id*="td_threadtitle_"]');
[].forEach.call(TDs, function(td) {
//Removes useless elements from the source
var tag = td.querySelector('img[src="images/misc/tag.png"]'); (tag != null) ? tag.parentNode.removeChild(tag) : false;
var div_small_font = td.querySelector('div[class="smallfont"]'); (small_font != null ) ? small_font.parentNode.removeChild(small_font) : false;
var span_small_font = td.querySelector('span[class="smallfont"]'); (small_font != null ) ? small_font.parentNode.removeChild(small_font) : false;
var span = td.querySelector('span'); (span != null ) ? span.parentNode.removeChild(span) : false;
//Change the look of some elements
var firstnew = td.querySelector('img[src="images/buttons/firstnew.gif"]'); (firstnew != null ) ? firstnew.src = "/img/icons/comment.gif" : false;
var boldtext = td.querySelector('a[style="font-weight:bold"]'); (boldtext != null ) ? boldtext.style.fontWeight = "normal" : false;
//Modify the lenght of the strings
var lenght_str = td.querySelector('a[id^="thread_title_"]');
if (lenght_str.textContent.length > 40) {
lenght_str.textContent = lenght_str.textContent.substring(0, 40);
lenght_str.innerHTML += "<span style='font-size: 6pt'> [...]</span>";
}
//Removes "Poll:" and Tabulation from the strings
td.querySelector('div').innerHTML = td.querySelector('div').innerHTML.replace(/(Poll)+(:)/g, '');
//Modify the URL from relative to absolute and add the target="_newtab" for the ICON
(td.querySelector('a[id^="thread_title"]') != null) ? td.querySelector('a[id^="thread_title"]').href += "&goto=newpost" : false;
(td.querySelector('a[id^="thread_goto"]') != null) ? td.querySelector('a[id^="thread_goto"]').href += "&goto=newpost": false;
(td.querySelector('a[id^="thread_title"]') != null) ? td.querySelector('a[id^="thread_title"]').target = "_newtab": false;
(td.querySelector('a[id^="thread_goto"]') != null) ? td.querySelector('a[id^="thread_goto"]').target = "_newtab": false;
//Store the td into the main 'html' variable
html += "<li>"+td.innerHTML+"</li>";
// console.log(td);
});
html += "</ul>";
//Send the html variable to the popup window
document.getElementById("content").innerHTML = html.toString();
};
xhr.responseType = 'document'; // Chrome 18+
xhr.send();
});
Following the background.js (the html just load /fancy-settings/source/lib/store.js and this script as Fancy-Setting How-To explains)
//Initialization fancy-settings
var settings = new Store("settings", {
"old_logo": false,
"max_topic_shown": "10"
});
//Load settings
var settings = settings.toObject();
//Listener who send back the settings
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.action == 'gpmeGetOptions') {
sendResponse(settings);
}
});
The console.log show the value as it has been cached, as i said.
If i set the value to "20", It remain default until i reload the extension.
If i change it to 30, it remain at 20 until i reload the extension.
If something more is needed, just ask. I'll edit the question.
The problem appears to be a conceptual misunderstanding. The background.js script in a Chrome Extension is loaded once and continues to run until either the extension or the Chrome Browser is restarted.
This means in your current code the settings variable value is loaded only when the extension first starts. In order to access values that have been updated since the extension is loaded the settings variable value in background.js must be reloaded.
There are a number of ways to accomplish this. The simplest is to move the settings related code into the chrome.extension.onRequest.addListener callback function in background.js. This is also the most inefficient solution, as settings are reloaded every request whether they have actually been updated or not.
A better solution would be to reload the settings value in background.js only when the values are updated in the options page. This uses the persistence, or caching, of the settings variable to your advantage. You'll have to check the documentation for implementation details, but the idea would be to send a message from the options page to the background.js page, telling it to update settings after the new settings have been stored.
As an unrelated aside, the var keyword in the line var settings = settings.toObject(); is not needed. There is no need to redeclare the variable, it is already declared above.

Categories

Resources