How to use headless driver in Python using Selenium - python-3.x

I have the below code
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
opts = Options()
opts.set_headless()
assert opts.headless # Operating in headless mode
browser = Firefox(options=opts)
txt=browser.get('https://duckduckgo.com')
print(txt.text)
However, when i execute it, i get the error "AttributeError: 'NoneType' object has no attribute 'text'"
I think I should get the text of the HTML.What am I doing wrong?

This error message...
AttributeError: 'NoneType' object has no attribute 'text'
...implies that the you have tried to extract the text attribute from a NoneType object.
get(url)
get(url) method loads a web page in the current browser session and doesn't returns anything.
Though you have tried to assign the variable text with the return value of get() as in:
txt=browser.get('https://duckduckgo.com')
txt still remains 'NoneType'
Solution
A bit more information about your usecase would have helped us to construct an answer in a better way. However if your are trying to retrieve the HTML you can use the page_source property as follows:
Code Block:
from selenium.webdriver.firefox.options import Options
from selenium.webdriver import Firefox
opts = Options()
# opts.set_headless()
opts.headless = True
assert opts.headless # Operating in headless mode
browser = Firefox(options=opts)
browser.get("https://duckduckgo.com")
print(browser.page_source.encode("utf-8"))
Console Output:
b'<html class="js no-touch opacity csstransforms3d csstransitions svg cssfilters is-not-mobile-device full-urls has-search-focus" lang="en_US"><!--<![endif]--><head>\n\t<meta http-equiv="X-UA-Compatible" content="IE=Edge">\n<meta http-equiv="content-type" content="text/html; charset=UTF-8;charset=utf-8">\n<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1">\n<meta name="HandheldFriendly" content="true">\n\n<link rel="canonical" href="https://duckduckgo.com/">\n\n<link rel="stylesheet" href="/s1771.css" type="text/css">\n\n<link rel="stylesheet" href="/o1771.css" type="text/css">\n\n\n\n<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" sizes="16x16 32x32">\n<link rel="apple-touch-icon" href="/assets/icons/meta/DDG-iOS-icon_60x60.png">\n<link rel="apple-touch-icon" sizes="76x76" href="/assets/icons/meta/DDG-iOS-icon_76x76.png">\n<link rel="apple-touch-icon" sizes="120x120" href="/assets/icons/meta/DDG-iOS-icon_120x120.png">\n<link rel="apple-touch-icon" sizes="152x152" href="/assets/icons/meta/DDG-iOS-icon_152x152.png">\n<link rel="image_src" href="/assets/icons/meta/DDG-icon_256x256.png">\n<link rel="manifest" href="/manifest.json">\n\n<meta name="twitter:card" content="summary">\n<meta name="twitter:site" value="#duckduckgo">\n\n<meta property="og:url" content="https://duckduckgo.com/">\n<meta property="og:site_name" content="DuckDuckGo">\n<meta property="og:image" content="https://duckduckgo.com/assets/logo_social-media.png">\n\n\n\t<title>DuckDuckGo \xe2\x80\x94 Privacy, simplified.</title>\n<meta property="og:title" content="DuckDuckGo \xe2\x80\x94 Privacy, simplified.">\n\n\n<meta property="og:description" content="The Internet privacy company that empowers you to seamlessly take control of your personal information online, without any tradeoffs.">\n<meta name="description" content="The Internet privacy company that empowers you to seamlessly take control of your personal information online, without any tradeoffs.">\n\n\n<link title="DuckDuckGo" type="application/opensearchdescription+xml" rel="search" href="https://duckduckgo.com/opensearch.xml?atb=v167-3__"></head>\n<body id="pg-index" class="page-index body--home body--onboarding">\n\t<script type="text/javascript">\nvar settings_js_version = "/s2472.js",\n locale = "en_US";\n</script>\n<script type="text/javascript" src="/lib/l113.js"></script>\n<script type="text/javascript" src="/locale/en_US/duckduckgo9.js"></script>\n<script type="text/javascript" src="/util/u344.js"></script>\n<script type="text/javascript" src="/d2613.js"></script>\n\n\n\n<script type="text/javascript">\n DDG.page = new DDG.Pages.Home();\n</script>\n\n\n\n\t<div class="site-wrapper site-wrapper--home js-site-wrapper">\n\t\n\t\t\n\t\t\t<div class="header-wrap--home js-header-wrap">\n\t<div class="header--aside js-header-aside is-hidden"><a class="header__button--menu js-side-menu-open" href="#">\xe2\x87\xb6</a><div class="header--aside__item showcase header__label"><span class="header__clickable js-hl-button" data-type="showcase"><span class="js-popout-trig" aria-haspopup="true" aria-label="Check out the list of things that we\'ve also made." role="button" aria-pressed="false"><span id="wedonttrack">Privacy, simplified.</span></span><span class="popout-trig js-popout"><span class="js-popout-link js-showcase-popout ddgsi ddgsi-down" aria-hidden="true" data-type="showcase"></span><div class="modal modal--popout modal--popout--bottom-left modal--popout--sm js-popout-main" data-type="showcase"><div class="modal__box"><div class="modal__body"><nav aria-labelledby="wedonttrack"><section class="showcase__dropdown-top"><ul aria-label="Here are some things that we made that you might like."> <li class="fix showcase__dropdown__list"><div class="woman-icon"></div><h1 class="showcase__heading">Get Our App & Extension</h1><p class="showcase__subheading">Protect your data on every device.</p></li><li class="fix showcase__dropdown__list"><div class="newsletter-icon"></div><h1 class="showcase__heading">Subscribe to our Privacy Crash Course</h1><p class="showcase__subheading">Learn about online privacy right in your inbox.</p></li><li class="fix showcase__dropdown__list"><div class="privacy-simplified-icon"></div><h1 class="showcase__heading">Protect Your Devices</h1><p class="showcase__subheading">Check out our privacy device guides.</p></li><li class="fix showcase__dropdown__list"><div class="spread-icon"></div><h1 class="showcase__heading">Spread DuckDuckGo</h1><p class="showcase__subheading">Help your friends and family join the Duck Side!</p></li></ul></section><section class="showcase__dropdown-bottom"><ul class="text-left" aria-label="We\'ve got even more things for you."><li class="fix showcase__dropdown__list"><div class="donations-icon"></div>$1,300,000 in privacy donations!</li><li class="fix showcase__dropdown__list"><div class="traffic-icon"></div>Over 29 Billion anonymous searches.</li><li class="fix showcase__dropdown__list"><div class="privacy-tips-icon"></div>Learn why reducing tracking is important.</li></ul></section></nav></div></div></div></span></span></div><div class="header--aside__item social"><a aria-label="Twitter" class="header--aside__item header--aside__twitter js-hl-twitter header__clickable header__link" href="https://twitter.com/duckduckgo"></a><span class="popout-trig js-popout header__clickable header__label js-hl-button" data-type="social"><span class="js-popout-link ddgsi ddgsi-down" aria-hidden="true" data-type="social"></span><div class="modal modal--popout modal--popout--bottom-left modal--popout--sm js-popout-main" data-type="social"><div class="modal__box"><div class="modal__body"><div class="social__link"><img class="social__icon js-lazysvg" data-src="/assets/icons/header/twitter-color.svg">Twitter</div><div class="social__link"><img class="social__icon--light js-lazysvg" data-src="/assets/icons/header/reddit-color.svg"><img class="social__icon--dark js-lazysvg" data-src="/assets/icons/header/reddit-dark.svg">Reddit</div><div class="social__link"><img class="social__icon--light js-lazysvg" data-src="/assets/icons/header/globe-alt.svg"><img class="social__icon--dark js-lazysvg" data-src="/assets/icons/header/globe-dark.svg">Blog</div></div></div></div></span></div></div>\n</div>\n\t\t\t<div id="" class="content-wrap--home">\n\t\t\t\t<div id="content_homepage" class="content--home">\n\t\t\t\t\t<div class="cw--c">\n\t\t\t\t\t\t\t\t<div class="logo-wrap--home">\n\t\t\t<a id="logo_homepage_link" class="logo_homepage" href="/about">\n\t\t\t\tAbout DuckDuckGo\n\t\t\t\t<span class="logo_homepage__tt">Learn More</span>\n\t\t\t</a>\n\t\t</div>\n\n\t\t\t\t\t\t<div class="search-wrap--home">\n\t\t\t\t\t\t\t\t\t<form id="search_form_homepage" class="search--home js-search-form search--adv search--focus" name="x" method="GET" action="/">\n\t\t\t<input id="search_form_input_homepage" class="js-search-input search__input--adv" type="text" autocomplete="off" name="q" tabindex="1" value="" autocapitalize="off" autocorrect="off">\n\t\t\t<input id="search_button_homepage" class="search__button js-search-button" type="submit" tabindex="2" value="S">\n\t\t\t<input id="search_form_input_clear" class="search__clear empty js-search-clear" type="button" tabindex="3" value="X">\n\t\t\t<div id="search_elements_hidden" class="search__hidden js-search-hidden"><input type="hidden" class="js-search-hidden-field" name="t" value="h_"></div>\n\t\t<div class="search__autocomplete" style="position: absolute; display: none;"><div class="acp-wrap js-acp-wrap"></div><div class="acp-footer is-hidden js-acp-footer"><span class="acp-footer__instructions">Shortcuts to other sites to search off DuckDuckGo</span><span class="acp-footer__link"><a class="no-visited js-acp-footer-link" href="/bang">Learn More</a></span></div></div></form>\n\n\t\t\t\t\t\t</div>\n\t\t\n\t\n\n\t\t\t\t\t\t<!-- en_US All Settings -->\n<noscript>\n <div class="tag-home">\n <div class="tag-home__wrapper">\n <div class="tag-home__item">\n The search engine that doesn\'t track you.\n <span class="hide--screen-xs">Learn More.</span>\n </div>\n </div>\n </div>\n</noscript>\n<div class="tag-home tag-home--slide no-js__hide js-tag-home"><div class="tag-home__wrapper"><div class="tag-home__item">The search engine that doesn\'t track you.<span class="hide--screen-xs"> <a class="tag-home__link js-tag-item-link" href="/spread">Help Spread DuckDuckGo!</a></span></div></div></div>\n <div id="error_homepage"></div>\n\n\n\t\n\t\t\n\t\t\t\t\t</div> <!-- cw -->\n\t\t\t\t</div> <!-- content_homepage //-->\n\t\t\t</div> <!-- content_wrapper_homepage //-->\n\t\t\t<div id="footer_homepage" class="foot-home js-foot-home"></div>\n\n<script type="text/javascript">\n\t{function seterr(str) {\n\t\tvar error=document.getElementById(\'error_homepage\');\n\t\terror.innerHTML=str;\n\t\t$(error).css(\'display\',\'block\');\n\t}\n\tvar err=new RegExp(\'[\\?\\&]e=([^\\&]+)\');var errm=new Array();errm[\'2\']=\'no search\';errm[\'3\']=\'search too long\';errm[\'4\']=\'not UTF\\u002d8 encoding\';errm[\'6\']=\'too many search terms\';if (err.test(window.location.href)) seterr(\'Oops, \'+(errm[RegExp.$1]?errm[RegExp.$1]:\'there was an error.\')+\' Please try again\');};\n\t\n\tif (kurl) {\n\t document.getElementById("logo_homepage_link").href += (document.getElementById("logo_homepage_link").href.indexOf(\'?\')==-1 ? \'?t=i\' : \'\') + kurl;\n\t}\n</script>\n\n\t\t\n\t\n\t<div class="nav-menu--slideout"><ul class="nav-menu__list"><i class="nav-menu__close js-side-menu-close">X</i><ul class="nav-menu--theme"><li class="nav-menu__heading"><span>Settings</span></li><li class="nav-menu__item"><ul class="nav-menu__themes"><li class="nav-menu__theme js-side-menu-theme theme-is-selected"><span class="nav-menu__theme-color"><span class="nav-menu__theme-color-top" style="background-color:#084999;"></span><span class="nav-menu__theme-color-bot" style="background-color:#888;"></span></span></li><li class="nav-menu__theme js-side-menu-theme"><span class="nav-menu__theme-color"><span class="nav-menu__theme-color-top" style="background-color:#333;"></span><span class="nav-menu__theme-color-bot" style="background-color:#888;"></span></span></li><li class="nav-menu__theme js-side-menu-theme"><span class="nav-menu__theme-color"><span class="nav-menu__theme-color-top" style="background-color:#3434d4;"></span><span class="nav-menu__theme-color-bot" style="background-color:#047d00;"></span></span></li><li class="nav-menu__theme js-side-menu-theme"><span class="nav-menu__theme-color"><span class="nav-menu__theme-color-top" style="background-color:#444;"></span><span class="nav-menu__theme-color-bot" style="background-color:#222;"></span></span></li></ul></li><li class="nav-menu__item clear">More Themes</li><li class="nav-menu__item">Other Settings</li><li class="nav-menu__item">!Bang Search Shortcuts</li></ul><ul><li class="nav-menu__heading"><span>Privacy Essentials</span></li><li class="nav-menu__item">Private Search</li><li class="nav-menu__item">App and Extension</li></ul><ul><li class="nav-menu__heading"><span>Why Privacy</span></li><li class="nav-menu__item">Privacy Blog</li><li class="nav-menu__item">Privacy Crash Course</li><li class="nav-menu__item">Help Spread Privacy</li></ul><ul><li class="nav-menu__heading"><span>Who We Are</span></li><li class="nav-menu__item">About Us</li><li class="nav-menu__item">Privacy Policy</li><li class="nav-menu__item">Careers</li><li class="nav-menu__item">Press Kit</li></ul><ul><li class="nav-menu__heading"><span>Keep in Touch</span></li><li class="nav-menu__item">Twitter</li><li class="nav-menu__item">Reddit</li><li class="nav-menu__item">Help</li></ul></ul></div><div class="badge-link badge-link--top badge-link--fadein ddg-extension-hide js-badge-link"><a class="badge-link__wrap js-badge-main-msg" href="https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/addon-385621-latest.xpi"><div class="badge-link__thumb"><img class="badge-link__thumb__img" src="assets/onboarding/robot-icon-frameless.svg"></div><p class="badge-link__title js-badge-link__title">Your data shouldn\xe2\x80\x99t be for sale.<br>At DuckDuckGo, we agree.</p><ol class="badge-link__bullets"><li class="badge-link__bullet"><span class="badge-link__bullet-num">1</span>Block advertising trackers.</li><li class="badge-link__bullet"><span class="badge-link__bullet-num">2</span>Keep your search history private.</li><li class="badge-link__bullet"><span class="badge-link__bullet-num">3</span>Take control of your personal data.</li></ol><div class="badge-link__btn-group"><span class="badge-link__btn btn btn--primary js-badge-link-button">Add DuckDuckGo to Firefox</span></div><span class="ddgsi badge-link__close js-badge-link-dismiss">\xc3\x97</span></a><div class="badge-link__wrap badge-link__wrap--hidden js-badge-cookie-msg"><div class="badge-link__cookie-msg"><p>Clear your cookies often?</p><p>Try our homepage that never shows these messages:</p><p><b>start.duckduckgo.com</b></p></div><span class="ddgsi badge-link__close js-badge-link-close">\xc3\x97</span></div></div><div class="onboarding-ed js-onboarding-ed"> <a class="onboarding-ed__arrow-teaser js-onboarding-ed-teaser" style="display: inline;"><img class="onboarding-ed__arrow-teaser__alpinist" src="/assets/onboarding/bathroomguy/teaser-2#2x.png"><div class="onboarding-ed__arrow-teaser__arrow-wrapper"><img class="onboarding-ed__arrow-teaser__arrow" src="/assets/onboarding/arrow.svg"></div></a><a class="onboarding-ed__arrow js-onboarding-ed-arrow" style="display: none;"><img src="/assets/onboarding/arrow.svg"></a><div class="onboarding-ed__slide onboarding-ed__slide-1 js-onboarding-ed-slide js-onboarding-ed-slide-1"><div class="onboarding-ed__content"><h1 class="onboarding-ed__title js-onboarding-ed-balance-text" style="">We don\xe2\x80\x99t store your<br data-owner="balance-text">personal information. Ever.</h1><p class="onboarding-ed__subtitle js-onboarding-ed-balance-text" style="">Our privacy policy is simple: we don\xe2\x80\x99t collect<br data-owner="balance-text">or share any of your personal information.</p><div class="js-onboarding-ed-button-small-1"><a class="btn onboarding-ed__button-small ddg-extension-hide" href="https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/addon-385621-latest.xpi">Add DuckDuckGo to Firefox</a></div></div><div class="onboarding-ed__image-container js-onboarding-ed-image-container-1"><img src="/assets/onboarding/bathroomguy/1-monster-v2--pre-animation.svg" class="onboarding-ed__image--placeholder" width="1200" height="460"></div></div><div class="onboarding-ed__slide onboarding-ed__slide-2 js-onboarding-ed-slide js-onboarding-ed-slide-2"><div class="onboarding-ed__content onboarding-ed__content--more-shadow"><h1 class="onboarding-ed__title js-onboarding-ed-balance-text" style="">We don\xe2\x80\x99t follow you<br data-owner="balance-text">around with ads.</h1><p class="onboarding-ed__subtitle js-onboarding-ed-balance-text" style="">We don\xe2\x80\x99t store your search history. We therefore have nothing<br data-owner="balance-text">to sell to advertisers that track you across the Internet.</p><div class="js-onboarding-ed-button-small-2"><a class="btn onboarding-ed__button-small ddg-extension-hide" href="https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/addon-385621-latest.xpi">Add DuckDuckGo to Firefox</a></div></div><div class="onboarding-ed__image-container js-onboarding-ed-image-container-2"><img src="/assets/onboarding/bathroomguy/2-ghost-v2.svg" class="onboarding-ed__image--placeholder" width="1200" height="460"></div></div><div class="onboarding-ed__slide onboarding-ed__slide-3 js-onboarding-ed-slide js-onboarding-ed-slide-3"><div class="onboarding-ed__content"><h1 class="onboarding-ed__title js-onboarding-ed-balance-text" style="">We don\xe2\x80\x99t track you in or out<br data-owner="balance-text">of private browsing mode.</h1><p class="onboarding-ed__subtitle js-onboarding-ed-balance-text" style="">Other search engines track your searches even when you\xe2\x80\x99re<br data-owner="balance-text">in private browsing mode. We don\xe2\x80\x99t track you \xe2\x80\x94 period.</p><div class="js-onboarding-ed-button-small-3"><a class="btn onboarding-ed__button-small ddg-extension-hide" href="https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/addon-385621-latest.xpi">Add DuckDuckGo to Firefox</a></div></div><div class="onboarding-ed__image-container js-onboarding-ed-image-container-3"><img src="/assets/onboarding/bathroomguy/3-bathtub-v2--pre-animation.svg" class="onboarding-ed__image--placeholder" width="1200" height="460"> </div></div><div class="onboarding-ed__slide onboarding-ed__slide-4 js-onboarding-ed-slide js-onboarding-ed-slide-4"><div class="onboarding-ed__close"><span class="js-onboarding-ed-dismiss onboarding-ed__close-dismiss">Dismiss forever</span><span class="ddgsi onboarding-ed__close-divider">|</span> <span class="onboarding-ed__close-back js-onboarding-ed-back-to-search">Back to search</span> </div><div class="onboarding-ed__content js-onboarding-ed-install"><h1 class="onboarding-ed__title js-onboarding-ed-balance-text" style="">Switch to DuckDuckGo and<br data-owner="balance-text">take back your privacy!</h1><p class="onboarding-ed__subtitle js-onboarding-ed-balance-text" style="">No tracking, no ad targeting, just searching.</p><div class="js-onboarding-ed-button"><a class="btn onboarding-ed__button ddg-extension-hide" href="https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/addon-385621-latest.xpi">Add DuckDuckGo to Firefox</a></div></div><div class="onboarding-ed__content js-onboarding-ed-spread" style="display:none"><h1 class="onboarding-ed__title js-onboarding-ed-balance-text" style="">Already a fan?<br>Invite friends to the Duck Side!</h1><p class="onboarding-ed__subtitle js-onboarding-ed-balance-text" style="">Share DuckDuckGo and help friends take their privacy back!</p><div><a class="btn onboarding-ed__button onboarding-ed__tweet-button js-onboarding-ed-tweet-button" target="_blank" href="https://twitter.com/?status=DuckDuckGo%20is%20my%20search%20engine%20of%20choice.%20%23ComeToTheDuckSide%20-%20we%20have%20privacy.%20https%3A%2F%2Fduckduckgo.com%2F%231">Tweet #ComeToTheDuckSide</a></div></div><div class="onboarding-ed__image-container js-onboarding-ed-image-container-4"><img src="/assets/onboarding/bathroomguy/4-alpinist-v2.svg" class="onboarding-ed__image--placeholder" width="1200" height="460"></div></div></div></div> <!-- site-wrapper -->\n\n\n<iframe id="iframe_hidden" src="/post2.html"></iframe></body></html>'
Here you can find a detailed discussion on What is a None value?

Related

Click on href link selenium python

I'm using Selenium and Python to try and click on each of the links shown. the same class name is used for the different websites.
`<div class="rp-table-col c7">
<span class="mobile-title">Action</span>
<a class="action" href="https://website.com" target="_blank">View</a>
</div>
<div class="rp-table-col c7">
<span class="mobile-title">Action</span>
<a class="action" href="https://website2.com" target="_blank">View</a>
</div>`
<div class="rp-table-col c7">
<span class="mobile-title">Action</span>
<a class="action" href="https://website3.com" target="_blank">View</a>
</div>`
<div class="rp-table-col c7">
<span class="mobile-title">Action</span>
<a class="action" href="https://website4.com" target="_blank">View</a>
</div>`
so far I'm able to get the 'View' text of all the classes but what I want to do is click on each of the links in the href (website, website2, website3, etc...)
y_list = driver.find_elements_by_css_selector("div[class*='rp-table-col c7']")
You can select all links and click them one by one using:
from selenium import webdriver
driver = webdriver.Chrome()
# Some code
links = [div.find_element_by_tag_name('a') for div in driver.find_elements_by_class_name('rp-table-col c7')]
for link in links:
link.click()
Warning! You must consider the possibility if clicking them switched the control to the new tab. So, I think you have the URLs saved in the links (list of <a> tags) variable, which you must use one by one by navigating to each URL. The links[0].get_attribute('href') will give you the first webdite URL.

Riot-tag inside of a loop

I have a xxx component, which when used with the riot-tag attribute and a standard HTML5 tag, works correctly: <article riot-tag="xxx"></article>. However when I use the riot-tag attribute inside of a loop, the tag is empty: <article each="{xxxTags}" riot-tag="{xxx}"></article>. Is using riot-tag in a loop possible at all? How can I make it work?
Additional explanation:
I have to generate several different, albeit similar components one by one. So I have an array to store them:
var xxxTags = [{tag: 'xxx'}, {tag: 'yyy'}, {tag: 'zzz'}];
Putting any of the textareas one by one manually for all of: xxx, yyy, zzz works fine and generates the respective components. However when I try to do it with each, they end up empty (no children) in chrome devtools, BUT otherwise identical to the ones put manually.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<my-tag></my-tag>
<!-- inlined tag definition -->
<script type="riot/tag">
<my-tag>
/*Standard, manual addition of different components (works)*/
<xxx></xxx>
<yyy></yyy>
<zzz></zzz>
/*Standard addition of same components in a loop (works)*/
<div each={myTags}>{tag}</div>
<br>
/*Addition of different components with "riot-tag" manually (works)*/
<div riot-tag="xxx"></div>
<div riot-tag="yyy"></div>
<div riot-tag="zzz"></div>
/*Addition of different components with "riot-tag" in a loop (DOESN'T WORK should look like the example above)*/
<div each={myTags} riot-tag="{tag}"></div>
this.myTags = [{tag: 'xxx'}, {tag: 'yyy'}, {tag: 'zzz'}];
</my-tag>
<xxx>
<p>X content</p>
</xxx>
<yyy>
<p>Y content</p>
</yyy>
<zzz>
<p>Z content</p>
</zzz>
</script>
<!-- include riot.js and the compiler -->
<script src="//cdn.jsdelivr.net/g/riot#2.2(riot.min.js+compiler.min.js)"></script>
<!-- mount normally -->
<script>
riot.mount('*');
</script>
</body>
</html>
Okay, looks, like the tags with riot-tag attribute are not mounted when generated with an each-loop (still looks like a bug?). For the above-mentioned code, adding this does the job:
this.on('mount', function() {
for(var i = 0; i < this.myTags.length; i++) riot.mount(this.myTags[i].tag);
});

structured data for free SoftwareApplication

I have structured data for SoftwareApplication in HTML page like this:
https://developers.google.com/structured-data/rich-snippets/sw-app
But if I check my structured-data:
https://developers.google.com/structured-data/testing-tool/
Its have warning:
offers: missing and recommended
My Android application is free. How can I write this for free App?
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
Price: $<span itemprop="price">1.00</span>
<meta itemprop="priceCurrency" content="USD" />
</div>
For the Offer, a price of $0 is valid and what Google SDT expects in this case.
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
Price: $<span itemprop="price">0.00</span>
<meta itemprop="priceCurrency" content="USD" />
</div>
If you don't want to show the price, you can use meta tag again for price.
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<meta itemprop="price" content="0.00" />
<meta itemprop="priceCurrency" content="USD" />
</div>
In general though, Google wants you to show the price to the user since it might create misleading or deceptive search experience. See policy:
https://developers.google.com/structured-data/policies#non-visible_content_and_machine-readable_alternative
There's a NEW SOFTWARE DATA TYPE (BETA).
The new software app data-type allows you to use offer type to set if it's free or not, now and here the rules are different, please refer to the following link for more info and warnings for not being "banned":
https://developers.google.com/search/docs/data-types/software-app
there's a difference between free app and a paid app that is free for a limited time:
If the app is free of charge, set offers.price to 0. For example:
"offers": {
"#type": "Offer",
"price": "0"
}
If the app has a price greater than 0, you must include offers.currency. For example:
"offers": {
"#type": "Offer",
"price": "1.00",
"priceCurrency": "USD"
}
regards.

Orbeon 4.2 switch case

I am trying to upgrade my orbeon to using the new orbeon 4.2. But I have a problem in the switch case that I used in my source code. It is having problem trying to toggle the case.
<xforms:action ev:event="xxforms-invalid" ev:observer="main">
<xforms:toggle case="invalid-form-case" if="instance('main')/current_session/student_module_regn_status = 'Close'"/>
</xforms:action>
<xforms:action ev:event="xxforms-valid" ev:observer="main">
<xforms:toggle case="valid-form-case" if="instance('main')/current_session/student_module_regn_status = 'Open'"/>
</xforms:action>
Below is the code for the switch case :
<xforms:switch>
<xforms:case id="invalid-form-case">
Closed
</xforms:case>
<xforms:case id="valid-form-case">
Open
</xforms:case>
Thanks
Here is a example that would reproduce the problem :
<html xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:widget="http://orbeon.org/oxf/xml/widget"
xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes"
xmlns:f="http://orbeon.org/oxf/xml/formatting"
xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>test</title>
<xhtml:link rel="stylesheet" href="/apps/uis-common/css/app-form.css" type="text/css"/>
<xforms:model>
<xforms:instance id="main">
<mains>
<test1>Open</test1>
</mains>
</xforms:instance>
<xforms:action ev:event="xxforms-invalid" ev:observer="main">
<xforms:toggle case="invalid-form-case" if="instance('main')/test1 = 'Close'"/>
</xforms:action>
<xforms:action ev:event="xxforms-valid" ev:observer="main">
<xforms:toggle case="valid-form-case" if="instance('main')/test1 = 'Open'"/>
</xforms:action>
</xforms:model>
</head>
<body dir="ltr">
<div>
<table width="100%" id="wrapper" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<xforms:switch>
<xforms:case id="invalid-form-case">
CLOSE
</xforms:case>
<xforms:case id="valid-form-case">
OPEN
</xforms:case>
</xforms:switch>
</td>
</tr>
</table>
</div>
</body>
</html>
it suppose to show "OPEN" as the "test1" is Open but no matter what the "test1" is, it just show "CLOSE"
The reason for the change is as follows:
In previous versions, the xxforms-valid and xxforms-invalid events dispatched to xforms:instance were dispatched during each revalidation. In recent versions, this behavior has changed, as mentioned in the compatibility notes.
As per the XForms processing model, upon XForms initialization, the following is done:
creation of models and instances
initial recalculate and revalidate
creation of the control tree
In your example, the first xxforms-valid or xxforms-invalid event is dispatched before the control tree is created. This means that your event handler doesn't find controls to toggle. Before 4.0, you would probably get at least one dispatch of xxforms-valid or xxforms-invalid after the control tree got created, so the toggle would work.
The better fix is probably to do something like this:
<xf:toggle
ev:event="xforms-ready"
if="xxf:valid(instance('main'), true())"
case="...">

Sitemesh layout doesn't work with g.include tag in Grails

I am rendering a view that combines a g.include invocation and a sitemesh layout.
The view would be something like this:
myview.gsp
<html>
<head>
<meta name="layout" content="checkout" />
</head>
<body>...
within the body there is an invocation to:
g.include(controller:"mycontroller", action:"myaction")
The problem is the sitemesh layout is never applied. If I remove the include invocation things work just fine.
I haven't found references to this problem in the site yet.
Has anyone found a workaround to this issue or a tip, will be much appreciated!
Thanks
-Pablo Duranti
My index file is like underlying:
<html>
<head>
<title>App Store For Publish, Download Android Apps</title>
<meta name="layout" content="main" />
<parameter name="sideBarSetting" value="main"/>
</head>
<body>
<g:if test="${flash.message}">
<div class="message">${flash.message}</div>
</g:if>
<g:announcements/>
<g:include controller="cache" action="showFeatured"/>
<g:include controller="cache" action="latestProducts"/>
<div class="push"></div>
<g:include controller="cache" action="mostPopular"/>
<div class="push"></div>
<g:include controller="cache" action="allCategories"/>
</body>
It works in Grails 1.0, 1.2.2 and now 1.3.7.
In each of actions you try to include, you can not render the view, but render the template instead. The template file can ONLY has fragments of HTML, it can NOT include the head, meta for layout, etc.
In my cache controller
def latestProducts = {
cache shared:true, validFor: 300
def htmlCacheManager = HtmlCacheManager.getInstance()
def key = 'latestProducts'
def content = htmlCacheManager.getHtmlContent(key)
if (!content) {
def products = productService.get5LatestProducts(params)
if (products){
content = g.render(template:'/common/product/productLatestListTemplate', model:['productInstanceList' : products, 'type':'latest'])
htmlCacheManager.store(key, content, Boolean.TRUE)
} else {
log.debug('No latest product found')
}
}
render content ?: ''
}
The template file:
<div class="list">
<fieldset>
<legend><g:message code="product.latest"/> <g:link action="feed" controller="product" params="['type':type]" target="_blank"><img src="${resource(dir:'images', file:'feed-icon.gif')}" height='16' width='16' alt="Feeds"/></g:link></legend>
<g:each in="${productInstanceList}" var="product">
<div class="product">
<g:render template="/common/product/productSingleListTemplate" model="['product':product]" />
</div>
</g:each>
</fieldset>
</div>

Resources