I'm creating a simple extension to show an icon on different URLs.
My background script includes:
chrome.tabs.onUpdated.addListener(function(o,r,m){for(var c=[
"URL1",
"URL2",
],a=0;a<c.length;a++)if(~m.url.indexOf(c[a])){chrome.pageAction.show(o);break}});
I would like to display a different page action icon for each of the two URLs. How should I proceed?
You appear to be looking for chrome.pageAction.setIcon().
I have re-written the code to be a bit more readable. I changed your use of Bitwise NOT, ~, to a test for !== -1. I used .some() to both loop through the urlList (a new Object containing both URLs and the icons) and to indicate if a match was found so that the page action icon could be hidden if the URL does not match. I assumed you wanted it hidden on a non-match, given that you were .show()ing it when there was a match.
var urlList=[{
url:"URL1",
icon:"/URL1icon.png"
},
{
url:"URL2",
icon:"/URL2icon.png"
}];
chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
if(!urlList.some(function(urlInfo){
if(tab.url.indexOf(urlInfo.url) !== -1) {
//The urlInfo.url must match the beginning of the tab's current URL.
chrome.pageAction.show(tabId);
chrome.pageAction.setIcon(tabId,{
path:urlInfo.icon
});
return true;
}
return false;
})) {
//Hide the icon if the URL does not match.
chrome.pageAction.hide(tabId);
}
});
Related
I'm using a plugin in ajax that filter some products of my site.
The url changes without reload the page.
I need indentify the url, split the words and add those class to body.
E.G: I filter some products, then my url changes to https://website.com/size=big/color=yellow,green,dark-red
So, this classes would be added to body: size big color yellow green dark-red
I have this code but I don't know how to make it work.
$(window).on('hashchange', function(e){
$('body').
});
Thanks.
UPDATE: Based on the comment thread in my answer it seems that you're really trying to convert the querystring values to css class names.
You can use the window.location.search to access all the querystring parameters.
function updateBodyClasses() {
var classNames = [];
// Use `.split()` to separate each key/value pair in the query by `&`
window.location.search.split('&')
// and loop over the results
.forEach(function(c) {
// Now split each pair by '='
var pair = c.split['='];
// Add the value to the left of the '='
if (pair.length > 0) {
classNames.push(pair[0]);
// if there are values on the right of the '='...
if (pair.length > 1) {
// ... split them by ',' and loop through them
pair[1].split(',').forEach(function(t) {
classNames.push(t);
});
}
}
});
// Now append those classNames to the body
$('body').addClass(classNames.join(' '));
}
// If your ajax plugin modifies the url via HTML5 history api...
$(window).on('popstate', updateBodyClasses);
// Update classes on page load
$(window).on('load', updateBodyClasses);
// If the ajax plugin modifies the url using window.location.replace()
// you'll need to check on an interval whether things have changed
// and update accordingly. the following example does this every 1000 milliseconds (or every second)
setInterval(updateBodyClasses, 1000);
I'm trying to automate some tasks using casperJS, and I need to open multiple popups. However, all popups have the exact same url (http://.../printit.aspx/...), so that whenever I use
this.withPopup(/printit/, function() {...});
it always opens the first popup. I can't access the other ones.
I suppose there are two possibilities :
close each popup after visiting it, but I can't find how to do this
accessing popups using another way than the URL regex /printit/. Maybe using casper.popups, but the documentation is very vague about this.
There is no easy and documented way of disambiguating two popups. The documentation says that casper.popups is an array-like property. So you could iterate over it. Judging by the code, the popups property itself is a pagestack. One can easily modify the pagestack.findByRegExp() function to do this kind of thing.
It seems that the casper.popups property contains duplicate entries, so one can filter them out.
casper.findAllPopupsByRegExp = function(regexp){
var popups = this.popups.filter(function(popupPage) {
return regexp.test(popupPage.url);
});
if (!popups) {
throw new CasperError(f("Couldn't find popup with url matching pattern %s", regexp));
}
// remove duplicates
var uniquePopups = [];
popups.forEach(function(p){
if (uniquePopups.indexOf(p) === -1) {
uniquePopups.push(p);
}
});
return uniquePopups;
}
casper.withPopup() accepts three types of inputs to identify a popup page. The third one is a the page object itself. So you can retrieve the matching popup page objects with findAllPopupsByRegExp(), select the one that you want and pass that to withPopup() to change into its context:
casper.then(function(){
var popups = this.findAllPopupsByRegExp(/printit/);
this.withPopup(popups[1], function(){
...
});
});
In my case i have a list of links. Every link calls some javascript that opens a new tab(=popup in casperjs), always with the same url (...\View.aspx).
Inside the tab i have to click a button that changes the url in the tab (...\List.aspx).
on("popup.loaded"...) is called twice, pushing every new page in the casper.popups array. They usually alternate, but for some reason (i guess asyncrony) not always: sometimes casper.popups[/*LAST*/].url matches /View\.aspx/, sometimes it matches /List\.aspx/.
I always had to use casper.withPopup( /*LAST VIEW.ASPX LOADED*/, ...); that was not always the last popup loaded and neither the one matching /View.aspx/ (it could be one of the oldes), so i had to find the latest loaded matching /View\.aspx/.
Here's my solution:
var is_view_loaded=false;
casper.on('popup.loaded', function(page) {
if(page.url.match(/View\.aspx/)) {
is_view_loaded=true;
}
}
// return last popup which url matches the required regexp
casper.getLastRegExPopup=function(regex) {
var l=casper.popups.length;
var i=l-1;
while(!regex.test(casper.popups[i].url)) {
i--;
if(i<0) return null;
}
return casper.popups[i];
}
Then in my core steps:
.
.
// clicked the link, must wait for popup (but which?!)
casper.waitFor(
function test() {
return is_view_loaded;
},
function then() {
var popup=casper.getLastRegExPopup(/View\.aspx/);
casper.withPopup(popup, function() {
// do things with "this"
});
is_view_loaded=false;
}
//, timeout
);
.
.
I've got a problem with switching between element classes - probably sth stupid, but I couldn't find the answer.
In my system I display a list of items. Now I want to be able to promote items, so that they appear at the top of the list. I created some backend infrastructure which works ok and added things to my frontend: a star (a span with star bg) next to every item's title and a jQuery script which is supposed to:
listen to 'click' event - when I click on a star
get some data- attributes from the span
post them to my controller
the controller checks if I'm allowed to promote items and replies 'true' or 'false'
if 'true' then I switch between 'gold-star' and 'silver-star' classes of the item
For some reason the classes don't switch - only when I refresh the page I can see the effect. I tried debugging with Firebug - it gets to the toggle line, but then nothing happens.
Here's the code:
<span class="silver-star promote">
$(".promote").bind("click", function() {
var $this = $(this);
var itemId = $this.attr("data-id"),
isPromoted = true;
if ($this.hasClass("gold-star")) {
isPromoted = false;
}
$.post('/promoteitems', { itemId: itemId, isPromoted: isPromoted }, function(allowPromotion) {
if (allowPromotion == true) {
$this.toggleClass("silver-star").toggleClass("gold-star");
}
});
});
Thanks in advance!
When you are getting a response back it might not recognise it as a boolean simple test would be to check response as string
From your comment on the question:
...the allowPromotion value is 'True' (with a capital T)...
That tell us it's a string, not a boolean. You don't want to just do if (allowPromotion), because that will toggle the classes even if you get back "False".
Instead:
if (allowPromotion == "True") { // Note the quotes and capital T
// ...toggle the classes
}
Or if you want to allow for possibly getting back something with a lower-case T at some point in the future:
if (/^\s*true\s*$/i.test(allowPromotion)) {
// ...toggle the classes
}
That's over-engineering it a bit (it'll work with "True", "true", " True " [note the spaces], and even an actual boolean true)...
I have a home.html and faq.html.
The faq page has many questions and their answers listed consecutively down the page. I want the answers hidden until a question is clicked that opens that answer. When another question is clicked, it will close the previous answer and open the new one. I'd like to use slideUp/slideDown or fadeIn/fadeOut for that, but not essential.
The home page has a link that when clicked, I want taken to the faq page and also have 'open' a specific answer, both from the one click; slideDown or fadeIn again not essential.
Is there a JavaScript that can be used to perform the task?
I have seen some posts with setvisibility type code somewhat acceptable for the faq page, but not that I can activate from my home page.
I am a novice, so I ask for the html code too that I can insert on both pages. A bigger chore than usual I know!
Many thanks.
NOTE
I now see a problem with my idea because of the following. I didn't mention it before but it would be neccessary.
Let me try to explain it.
I now find that to have a link on one page open another page at a particular position down that page will
correctly position the page to that point IF previous content on that page is not hidden.
If previous content is visibility: hidden;, that point where the page will open at is innacurate. In other words, it opens at a point below intended, a point at which is correct if previous content is not hidden.
I hope that makes some sense.
I will soon look at whether display:none; is better suited for this before I look at my original questions.
Thanks to those who have helped me to date, you have spent a lot of time for me.
Try this one
Reference
$(function() {
$('div.answer').hide();
$('a.question').before('<span class="faqplusminus dark nounderline">[+]</span>');
$('a.question').click(function() {
$('div.answer').slideUp('slow', 'easeInOutExpo');
$('span.faqplusminus').html('[+]');
var slidedownelement = $(this).closest('div.faq').find('div.answer').eq(0);
if(!slidedownelement.is(':visible')) {
slidedownelement.slideDown('slow', 'easeInOutExpo');
slidedownelement.parent().find('span.faqplusminus').html('[-]');
}
});
});
You can add querystring parameters to the request for the faq page and read the querystring using javascript on the faq page. Depending on the parameters you pass, you could do your desired animations.
In home.html: You would create the links with the query string param like so:
Link to FAQ
In faq.html: you would need to read the querystring parameter and depending on the value, call the javascript function that actually handles the show/hide of questions.
To read querystring parameters in javascript you need to parse window.location.search. Here is a javascript helper that you can use:
var QueryString = function () {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
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 first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = pair[1];
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]], pair[1] ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(pair[1]);
}
}
return query_string;
} ();
You can then access QueryString.question
I created a select from with popularity,high_to_low and low_to_high as options. I want the page to respond to these options dynamically using the ajax code
var http_option = createRequestObject();
function verifyRequest()
{
var option = document.getElementById("option").value;
if ( option )
{
var url = 'respond.pl?option='+option;
http_option.open('get', url );
http_option.onreadystatechange = handleResponse;
http_option.send(null);
}
}
function handleResponse()
{
if(http_option.readyState == 4 && http_option.status == 200)
{
var response = http_option.responseText; // Text returned FROM perl script
if(response) { // UPDATE ajaxTest content
document.getElementById("id_id").innerHTML = response;
}
}
If the value of the option is 1, images are displayed as stored in DB.
If the option is 2, images are to be displayed in descending order and
If the option is 3, images are to be displayed in ascending order
The respond.pl contain appropriate code for this sorting according to options and display images in a specified div tag.
The problem is that the page responds to the options only once and the next time on changing the option, the value of options shows "on" and not the numerals 1,2,3
I need this not only to sort images but also for faceting. If this is not the right option suggest the appropriate methods used for it.
It looks like your server-side program is returning HTML. And I think that's probably a mistake in this situation. I suggest returning JSON instead. Then, you can create an onChange event handler for your selector which simply re-orders the display. There are almost certainly a number of jQuery plugins that do this without you needing to write very much code.