Binding a text containing javascript to innerHTML in a template - javascript

For a metro style app, in Windows 8, I have a list of article that i pass to a flip View Control. Each Article have a description text in HTML which contains javascript. I know we have to use this function to load unsafe content to innerHTML :
var someElement = document.getElementById('someElementID');
MSApp.execUnsafeLocalFunction(
function() { someElement.innerHTML = '<div onclick="console.log(\"hi\");">hi</div>' }
);
But how can i achieve that when my innerHTML property is within a template?
here is my template :
<div id="ItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="itemDetail fragment">
<header aria-label="Header content" role="banner">
<!-- <button class="win-backbutton" aria-label="Back" disabled></button>-->
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle"></span>
</h1>
</header>
<section aria-label="Main content" role="main">
<article>
<img class="article-image" src="#" style="width: 300px; height: 200px;" data-win-bind="src: urlImage; alt: title" />
<div class="item-content" data-win-bind="innerHTML: description"></div>
</article>
</section>
</div>
</div>
for this flipVIew :
<div id="basicFlipView"
data-win-control="WinJS.UI.FlipView"
data-win-options="{itemTemplate:select('#ItemTemplate')}">
</div>
and here is how i Fill it :
var dataControl = document.getElementById("basicFlipView").winControl;
dataControl.itemDataSource = dataList.dataSource;
dataControl.currentPage = myState.index;
Thank you very much for your help
EDIT : As Dominic Hopton suggested I used a WinJS.Binding.initializer. This is a quite complex way of doing a binding. I've done this but it doesn't work properly. Do you see something wrong :
var toUnsafeHTML = WinJS.Binding.initializer(
function toUnsafeHTML(source, sourceProperty, dest, destProperty) {
function setUnsafeHTML() {
MSApp.execUnsafeLocalFunction(
function () { dest.innerHTML = source.innerHTML }
);
}
return WinJS.Binding.bind(source, {
innerHTML : setUnsafeHTML}
);
}
);
//
// Binding initializers have to be public, so publish this out
// via a namespace
//
WinJS.Namespace.define("TemplateControl", {
toUnsafeHTML: toUnsafeHTML
});
and in the html :
<div id="ItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="itemDetail fragment">
<header aria-label="Header content" role="banner">
<!-- <button class="win-backbutton" aria-label="Back" disabled></button>-->
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle"></span>
</h1>
</header>
<section aria-label="Main content" role="main">
<article>
<img class="article-image" src="#" style="width: 300px; height: 200px;" data-win-bind="src: urlImage; alt: title" />
<div class="item-content" data-win-bind="innerHTML: TemplateControl.toUnsafeHTML"></div>
</article>
</section>
</div>
</div>
It never enter the setUnsafeHTML function...

I'm not sure this is even possible using databinding, at least not using any of several techniques I tested.
That being said...even if you COULD do this...if the articles you are loading are coming from the Internet, this would be a VERY bad idea.
If you load script from the network, you expose yourself to the possibility that it contains malicious code. There's a reason this limitation exists, which is to protect you (and more importantly, those who use your app) from potential exploits.
If you haven't already, please read the docs for execUnsafeLocalFunction, as they detail why attempting to inject script from the web in the local app context is a bad idea:
http://msdn.microsoft.com/en-us/library/windows/apps/Hh767331.aspx
See also (the section titled "Dynamically adding HTML"):
http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx
and:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465388.aspx
which lists the tags, attributes, and CSS properties that are considered safe or unsafe.
Hope that helps!

Related

modify / move an existing html tag in the DOM (javascript)

I want to move my div class="contentlinks" tag with its content, to place it in the div class="row" after the div class="col-12".
Here is the basic html architecture :
<span id="data">
<section id="" class="thesectionQ">
<div class="container">
<div class="row">
<div class="col-12">
<h1>Title</h1>
</div>
</div>
</div>
</section>
<div class="col-12 contentlinks">
<a class="btn">link1</a><a class="btn">link2</a>
</div>
</span>
Tags are dynamically created in js... my problem is that I can't seem to use appendChild ...
my problem is that I can't seem to use appendChild ...
I'm trying to target my section with a class="thesectionQ" in a variable as well as my div class="contentlinks" that I want to move :
for example...
var thedata2 = document.getElementById('data').getElementsByClassName('thesectionQ');
var thedata = document.getElementById('data').getElementsByClassName('contentlinks');
thedata2.appendChild(thedata);
but I have errors ... and too often
give section id so it become easy.
document.querySelector('#sectionId div.row')
.appendChild(document.querySelector('div.contentlinks'))

click event is not working. For few elements it is for few its not

In my code for cmd and normal its working, but for #aboutme its not. Don't know why such event is getting ignored while its working for the above snippet.
var normal = $(".normal");
var cmd = $(".cmd");
normal.on("click", function(){
$(".UI").show();
$(".console").hide();
});
cmd.on("click", function(){
$(".console").show();
$(".UI").hide();
});
$("#aboutme").on("click",function(){
console.log("okay");
});
My Html Code: class dashboard acts as a wrapper.
<div class="dashboard ">
<div class="option">
<div class="normal">Normal</div>
<div class="cmd">Terminal</div>
</div>
<hr style="background-color: white;">
<div class="console">
</div>
<div class="UI ">
<div class="showcase">
<div id="aboutme">
<h2><span>»About</span></h2>
<p>Self-motivated fresher seeking a career in recognized organization to prove my skills and utilize my knowledge and intelligence in the growth of organization.</p>
</div>
<div id="Skills">
<h2><span>Skills</span></h2>
<p> <kbd>Programming Languages</kbd> : Python, Node.js, C++</p>
<p> <kbd>Platform & Development Tools</kbd> : VS Code , Spyder and Jupiter Notebook</p>
</div>
</div>
</div>
Seems to work, can you provide your full HTML
$("#aboutme").on("click",function(){
console.log("okay");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="aboutme">Test</button>

How clone image in pure js

I wrote JS to clone image and attached this action to button.
It works but I'm not sure that this better way to do it.
My questions:
is it correct to use querySelector to return elements, or is it better to add additional classes or id for buttons and pictures?
use cloneNode is optimal or better use other ways in this case?
(function() {
'use strict';
document.querySelector('button[action="button"]').addEventListener('click', function() {
let image = document.querySelector('img[alt="Dog"]');
let cln = image.cloneNode(true);
document.getElementById('image-section').appendChild(cln);
});
})();
<body>
<div id="overview">
<section class="section--center">
<button action="button">Yeah, I want more dogs!</button>
</section>
<section class="section--center" id='image-section'>
<img src="https://www.purina.com/sites/g/files/auxxlc196/files/styles/kraken_generic_max_width_480/public/HOUND_Beagle-%2813inch%29.jpg?itok=lN915WHC" alt="Dog" style="width: 150px">
</section>
</div>
</body>
Another option is updating innerHTML, but it's not better.
An approach should solve a task, so it depends on the task.
(function() {
'use strict';
document.querySelector('button[action="button"]').addEventListener('click', function() {
document.getElementById('image-section').innerHTML +=
document.querySelector('img[alt="Dog"]').outerHTML;
});
})();
<body>
<div id="overview">
<section class="section--center">
<button action="button">Yeah, I want more dogs!</button>
</section>
<section class="section--center" id='image-section'>
<img src="https://www.purina.com/sites/g/files/auxxlc196/files/styles/kraken_generic_max_width_480/public/HOUND_Beagle-%2813inch%29.jpg?itok=lN915WHC" alt="Dog" style="width: 150px">
</section>
</div>
</body>

Change position of an element using CSS/JS only

I am using Uikit 2 (https://getuikit.com/v2) - and I need to solve a problem.
I got this markup: https://codepen.io/anon/pen/jZwNeB
Now I need to do the following. This part:
<div class="toc uk-panel uk-panel-box-primary sticky-toc" style="margin: 0px;"> ...</div>
Should be shown on the left side - right under the time datetime part. But - and this is important: I can not change the source itself. I can only add a class to toc uk-panel uk-panel-box-primary sticky-toc and add custom CSS and custom JS.
Any idea how to solve this?
var obj = document.getElementById("node");
var parent = document.getElementById("parent");
parent.appendChild(obj);
Here, node is the "toc uk-panel uk-panel-box-primary sticky-toc" element.
parent is the "uk-width-large-1-4" element
You can obviously use any other DOM method than the one I have used.
So, if you want to select the DOM of the entity using its class name class, you have to use getElementsByClassName("big long class name")[0] to correctly reference that entity
I just wanted to highlight the appendChild method
I believe the best answer is using CSS, but because I don't know about getukit and I don't know how to solve this using CSS only.
Here you can try with jQuery. Tell me if you want do this using pure JS.
<link href='https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/css/uikit.min.css' rel='stylesheet'>
<div class="uk-grid">
<div class="uk-width-large-1-4">
<p class="uk-article-meta tm-article-date uk-margin-small selectionShareable">
<time datetime="2018-02-12T12:00:58+00:00">12.02.18</time>
</p>
</div>
<div class="uk-width-large-3-4">
<h1 class="uk-article-title">Test Content</h1>
<div class="uk-margin">
<div class="uk-sticky-placeholder" style="height: 52px; margin: 0px;">
<div class="toc uk-panel uk-panel-box-primary sticky-toc" style="margin: 0px;">
<ol class="toc-list ">
<li class="toc-list-item">
Testa
<ol class="toc-list is-collapsible">
<li class="toc-list-item">Test 2</li>
</ol>
</li>
</ol>
</div>
</div>
<p class="selectionShareable">Test Content.</p>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(function(){
function recreate(){
let newElem = $('.sticky-toc').clone();
$('.sticky-toc').remove();
$('.tm-article-date').after(newElem);
}
recreate();
})
</script>

Get data from element without id or class

I am building a Chrome extension (and therefore can only use JavaScript) and I need to get the link that resides in the h2 with the heading2 class.
However, there are multiple h2 items with that class (not shown here), and I will not know what the link will point to, as it changes monthly.
In this example, the content of the header is "Think before you tweet". It will always be under another header that contains the words "Featured Topic."
What I am looking to get is the /think_before_you_tweet from the href= of that h2 item. It shows that I have already completed the topic underneath the h2, but that will not always be the case.
Here is the code for the website:
<div class="chosen_for_you_section">
<div class="internal_container">
<h2 class="section_header"><img src="/public/s360/img/360-spinner.png" class="s360LogoHeader">Featured Topic <i class="fa fa-info-circle"></i> <span class="infoTxt">Read about what to do</span></h2>
<article class="article_block masonry_item " data-article_id="431">
<div class="article_image">
<img src="/thumb/public/media/nh/images/twitter_tweet_think_before_send.png?q=&h=278" />
<i class="fa fa-check-square-o article_complete article_type_icon" title="Article"></i>
<div class="action_icons">
<span class="like "><a title="Favorite"><i class="fa fa-heart"></i></a></span>
</div>
</div>
<header>
<h2 class="heading2">Think Before You Tweet!</h2>
<div class="article_required_complete">Congratulations, you've completed this required topic.</div>
<div class="category_blocks">
<p>
Social Media
</p>
</div>
</header>
</article>
<div class="focus_items">
<div class="home_side">
<p>
<img alt="" src="" style="width: 430px; height: 422px;" /><!-- I hid the img src here because it reveals some personal information and is not important -->
</p>
<p></p>
</div>
</div>
</div>
</div>
I can use jQuery in my extension, but I do not have any back-end capabilities.
Use jQuery :contains selector:
$('h2.section_header:contains("Featured Topic") + article a')[0].href
Looks like you've gotta loop through the h2.section_header headers, see if the text matches whatever you want, and then grabs the link from the header following itself.
$('h2.section_header').each(function(index, element) {
var $element = $(element);
if ($element.text().match(/Featured Topic/i)) {
$('#result').html($element.next('article').find('h2.heading2 a').attr('href'));
}
});
#result {
border: 3px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>
<div class="chosen_for_you_section">
<div class="internal_container">
<h2 class="section_header"><img src="/public/s360/img/360-spinner.png" class="s360LogoHeader">Featured Topic <i class="fa fa-info-circle"></i> <span class="infoTxt">Read about what to do</span></h2>
<article class="article_block masonry_item " data-article_id="431">
<div class="article_image">
<img src="/thumb/public/media/nh/images/twitter_tweet_think_before_send.png?q=&h=278" />
<i class="fa fa-check-square-o article_complete article_type_icon" title="Article"></i>
<div class="action_icons">
<span class="like "><a title="Favorite"><i class="fa fa-heart"></i></a></span>
</div>
</div>
<header>
<h2 class="heading2">Think Before You Tweet!</h2>
<div class="article_required_complete">Congratulations, you've completed this required topic.</div>
<div class="category_blocks">
<p>
Social Media
</p>
</div>
</header>
</article>
<div class="focus_items">
<div class="home_side">
<p>
<img alt="" src="" style="width: 430px; height: 422px;" /><!-- I hid the img src here because it reveals some personal information and is not important -->
</p>
<p></p>
</div>
</div>
</div>
</div>
with jQuery's :contains selector use this:
jQuery('h2:contains("Featured Topic") ~ article h2.heading2 a').attr('href')
try at http://jsfiddle.net/ug01a0d2/
without jQuery try to bind to class "section_header" or use a cycle with the textContent check to iterate all "h2.section_header"
If there are multiple H2 class heading2 :
$('h2[class*="heading2"] a').each(function(){
var href = $(this).attr('href');
// Do what you want with this href
});
Use XPath! The syntax is pretty, uh, unfortunate, but it's very powerful:
var result = document.evaluate('//h2[#class="section_header"]/following-sibling::article//h2[#class="heading2"]/a', document, null, XPathResult.ANY_TYPE, null );
That should select that anchor node. I'm not sure if it's available to extensions, but Chrome defines a handy helper method called $x that eliminates all that boilerplate around the query.
More information: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript

Categories