DomCrawler is removing part of the html - symfony

When I get the content without DomCrawler, I get the html with custom tags like #click but when I use $this->crawler->filter('something')->html() DomCrawler is removing my #click tags.
Here an example without using DomCrawler:
And here is using DomCrawler:
As you can see, DomCrawler is removing all the #clicks, how can I stop this?

Unfortunately, you can't. DomCrawler uses DOMDocument under the hood and will not allow the "#click". Also:
The DomCrawler will attempt to automatically fix your HTML to match the official specification.
The modifiers to disable this would be LIBXML_HTML_NOIMPLIED which is not used in the addHmlContent method of DomCrawler:
//... Symfony\Component\DomCrawler\Crawler.php
$dom->loadHTML($content);
// ...
and even calling #$dom->loadHTML($content, LIBXML_HTML_NOIMPLIED); would not work in your case.
Example:
$html = <<<TEST
<html>
<div class="test" #click="something"></div>
</html>
TEST;
dump($html);
//<html>\n
// <div class="test" #click="something"></div>\n
//</html>
// Symfony Crawler
$crawler = new \Symfony\Component\DomCrawler\Crawler();
$crawler->addHtmlContent($html);
dump($crawler->html());
//<body>\n
// <div class="test"></div>\n
//</body>
// Custom crawler with LIBXML_HTML_NOIMPLIED
$crawler = new \MyCrawler\Crawler();
$crawler->addHtmlContent($html);
dump($crawler->html());
// <div class="test"></div>

You could replace the #click with x-on:click which has the exact same effect and is valid HTML at the same time.

Related

Isolating select2 version doesn't work

I'm using Select2 on my WordPress plugin and I need to isolate the version I load in order to avoid conflicts with other plugins also using Select2.
I have found this answer by #Kevin Brown where he proposes to use save the select2 function into a variable just after being loaded and before removing it to avoid issues with other loads:
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>
<script>
var myOwnSelect2 = $.fn.select2;
delete $.fn.select2;
</script>
The problem I have is that it works in edit-post.php pages, but not anywhere else. I mean, "select" tags/elements are being replaced on edit-post.php pages but not at my plugin settings page. The code on each page looks like this:
edit-post.php
HTML
<div class="myplugin-metabox">
...
<select name="_myplugin_item" class="searchable select2-hidden-accessible" data-placeholder="Select an item..." tabindex="-1" aria-hidden="true">
<option>...</option>
</select>
...
</div>
Javascript
myOwnSelect2.call( $('.myplugin-metabox select'), { dropdownAutoWidth: true, minimumResultsForSearch: Infinity } );
admin.php?page=myplugin
HTML
<div id="myplugin-settings">
...
<select id="option-1" name="myplugin-option-1" class="">
<option value="all">...</option>
...
</select>
...
</div>
Javascript
myOwnSelect2.call( $('#myplugin-settings select'), { dropdownAutoWidth: true, minimumResultsForSearch: Infinity } );
If I don't use any isolation method, everything within my plugin is working just fine... but I need the isolation because many other popular plugins load their own version/copy of Select2.
Javascript initializations are made on the same file. Keeping isolation, if I remove initialization for edit-post.php selects, selects on my plugin settings page doesn't get converted to Select2 dropdowns.
Any suggestion of what I might be doing wrong?
Thanks!
Well, I found the cause of the problem myself. I'm writing it here so it might be of help to others in my situation.
The thing was that I was referencing jQuery as "$", when I should have referenced it as "jQuery". Check out the code below:
Didn't work (in my case):
<script>
var myOwnSelect2 = $.fn.select2;
delete $.fn.select2;
</script>
Does work (in my case):
<script>
var myOwnSelect2 = jQuery.fn.select2;
delete jQuery.fn.select2;
</script>

Meteor Blaze To Do App checked condition

(Super new to meteor)
I've gone through the meteor todo app tutorial and on the checking off and deleting tasks part It says that
If you try checking off some tasks after adding all of the above code, you will see that checked off tasks have a line through them. This is enabled by the following snippet:
<li class="{{#if checked}}checked{{/if}}">
With this code, if the checked property of a task is true, the checked
class is added to our list item. Using this class, we can make
checked-off tasks look different in our CSS.
Is there any way to have this apply to a different tag, and not the list? so basically have it say
With this code, if the checked property of a task is true, the updatedstyle
class is added to our img tag. Using this class, we can make
checked-off tasks make images look different in our CSS.
You can put the {{#if}} anywhere you want in your template, not just in the list item. If I understand your specific question:
<li>Some item
<img class="{{#if checked}}updatedstyle{{/if}}" src="/myImg.png">
</li>
Per #blueren, the parameter to the {{#if}} is evaluated as a truthy or falsy value. It can be a key in the current data context (i.e. this.checked) or can be returned by a helper.
If you want a class reactively binded to html tag in the template, you can do it like that:
Template code:
<template name="MyTemplate">
<img src="my/img/path.jpg" class={{checked.img}}/>
<ul>
<li class={{checked.li}}>My List Entry</li>
</ul>
</template>
Helper Code:
Template.MyTemplate.helpers({
checked() {
let liClass = '';
let imgClass = '';
//your checked condition
if(document.getElementById('myCheckBox').checked) {
let liClass = 'checked';
let imgClass = 'updatedstyle';
}
return {
li: liClass,
img: imgClass
};
}
});
That way you can bind multiple classes with different names to the checked input value.

Angular2 create a component that displays the content of an external webpage

I need to create a component that displays the content of another webpage.
So for instance if I have the site of stackoverflow, I would like to create a component that does a http request and displays the content through my app. By the way, the external website is just django-rest-swagger and to access it, I need to include a header everytime I access it. So, when I make the request for the external site content I need to inlclude the header x-forwarded-host.
<div>
<html> CONTENT OF EXTERNAL WEBSITE </html>
</div>
thank you
#Component({
selector: ...
template: `<div [innerHTML]="fetchedHtml"></div>
})
export class ExternalHtml {
constructor(http:Http) {
var headers = new Headers();
headers.append('x-forwarded-host', 'foo');
http.get('someUrl', {headers: headers}).subscribe(response => {
this.fetchedHtml = response.json();
}
}
See also
In RC.1 some styles can't be added using binding syntax
Alternatively you can also use an iframe to display the fetched HTML.
You can display it as follows:
<div [innerHTML]="contentOfTheExternalWebsite">
</div>

how to attach events to generated html of a template in Meteor 0.8 with Blaze

I'm using Meteor 0.8 with Blaze and I want to attach events dynamically to HTML contents generated using UI.toHTML of a template. The functionality I am looking for is the alternative to Spark.attachEvents in Blaze.
What I have done so far is that I have created the following template to be used like a widget/component.
<template name="postLinks">
<div id="link-popover-wrapper" >
<ul class="link-popover">
{{#each linkOptions}}
<li><a tabindex="-1" class="link-action" id="link-{{value}}" href="#">{{label}}</a>
</li>
{{/each}}
</ul>
</div>
</template>
And the template is used in Helper of the myPostItem template.
Template.myPostItem.events({
'click .post-item-link-picker': function (evt, tmpl) {
var tempData = {linkOptions:[{label:'Favorite', value : 'favorite'}, ...]};
// Get the HTML content of the template passing data
var linkContent = UI.toHTML(Template['postLinks'].extend({data: function () { return tempData; }}));
// Attach events to the linkContent like in Spark
/*Spark.attachEvents({
'click link-action': function (e, tmpl) {
alert("Component item click");
}
}, linkContent);*/
// Popover the content using Bootstrap popover function
}
});
So my requirement is to attach events to a dynamically generated HTML contents.in the linkContent like Spark.attachEvents after the following line as mentioned in above code.
var linkContent = UI.toHTML(Template['postLinks'].extend({data: function () { return tempData; }}));
Hope somebody can help to find a way to do this in Meteor 0.8 with Blaze.
The reason that Spark-generated HTML could be directly inserted into the DOM is because it had "landmarks" - annotations that could be processed into events and handlers when the DOM nodes were materialized.
Blaze works differently - it inserts a UI component into the DOM directly and attaches events, using the UI.render function. It cannot directly attach template events to the DOM if you use UI.toHTML because there are none of the annotations that Spark had for doing this.
I'm also using Bootstrap popovers in my app, and as far as I know there's no clean way to insert reactive content into a popover. However, you can approximate it with a hack in the following way:
In the content callback of the popover, render the template with UI.toHTML - a nonreactive version of the content. This is necessary because otherwise the popover won't be sized and positioned properly.
Using a Meteor.defer call, replace the popover contents with reactive content, so they'll continue updating while the popover is open.
Because Bootstrap uses jQuery, you should be fine with removing reactive logic properly, for now. Future versions of Meteor will probably have easier ways to do this.

Selenium+PHPunit: foreach element in collection

I am looking for a way to work with collections of elements in Selenium with PHPunit. Let's say I have the below code:
<div class="test">aaa</div>
<div class="test">bbb</div>
<div class="test">ccc</div>
I would like to be able to work on all the <div> elements inside an each loop, let's say by selecting the elements based on their class with //div[#class='test']
$divs = ... //
foreach ($divs as $div) {
// do something
}
The function to get the content of your entire page is :- getHtmlSource()
So your final function call to load HTML would be something like ..
$dom->loadHTML($this->getHtmlSource());
In PHP, if you want to work with some HTML data, a great solution is using the DOMDocument class -- which means being able to work with DOM methods -- via its DOMDocument::loadHTML() method.
Loading your HTML with DOMDocument :
$dom = new DOMDocument();
$dom->loadHTML('HERE YOUR HTML STRING');
You can then instanciate a DOMXpath object :
$xpath = new DOMXPath($dom);
Which will allow you to extract data from the HTML, using XPath Queries, with DOMXPath::query() :
$entries = $xpath->query('//div[#class="test"]'); // notice quotes
if ($entries->length > 0) {
foreach ($entries as $entry) {
// Work on the $entry -- which is a DOM node/element
}
}

Resources