I created a custom widget in Magento 2 and would like to dynamically change the page title in the Block's code. However, I can't seem to overwrite the page title that gets set in Magento\Cms\Block\Page::_prepareLayout().
From inside my block I have the following function. As you can see I've tried a handful of ways to make the changes to see if I can get any result.
public function _prepareLayout()
{
$this->pageConfig->getTitle()->set('TESTING');
$this->pageConfig->getTitle()->append(' - TEST');
$this->pageConfig->setMetadata('title', 'Meta Title Test');
$this->pageConfig->addBodyClass('mytestclass');
$pageMainTitle = $this->getLayout()->getBlock('page.main.title');
if ($pageMainTitle) {
$pageMainTitle->setPageTitle('Page Heading Title');
}
return parent::_prepareLayout();
}
I ran the page load through xDebug and according to the debugger my _prepareLayout does get called after the default _prepareLayout that originally sets the title. And looking through the variables in the debugger the above code all appears to be successful. However, when the page actually renders none of the above is implemented. Not even the body tag added.
I don't see much out there in regards to trying to do this from a widget block. I'm wondering if there is something I'm missing here, or if I'm approaching this the wrong way. Maybe there's a better way to achieve what I want.
Yes, I cleared, flushed, and disabled all of the cache.
Using Magento version 2.1.2
Any guidance would be greatly appreciated!
Related
I'm using attempting to add an "onclick" object to a page in a singlesite (i.e. rather than multisite) WordPress that triggers an event. The code is:
Send a voice message
When attempting to save the code, WordPress strips the onclick object leaving:
Send a voice message
A user on another forum suggested that this restriction should only apply to multisite non-superadmin users. Again, this is a siglesite with only one admin user.
It is understood that WordPress removes "onclick" from HTML to prevent malicious code. Still, does anyone know how to resolve this?
Thanks.
It appears that with current Wordpress (I'm on 4.9.4), TinyMCE does the filtering directly on the editor screen, not when the form is submitted. The allowedtags and allowedposttags don't seem to matter, so the solution above does not solve the problem for me.
The method I have developed uses the tiny_mce_before_init filter to alter the allowed tags within TinyMCE. The trick is to add the extended_valid_elements setting with the updated versions of the elements allowed for a.
First, look in the page http://archive.tinymce.com/wiki.php/Configuration3x:valid_elements to find the current value for a, which right now is
a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur]
And add to the end of that the onclick attribute:
a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick]
Then use that in the filter function like this:
function allow_button_onclick_mce($settings) {
$settings['extended_valid_elements'] = "a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick]";
return $settings;
}
add_filter('tiny_mce_before_init', 'allow_button_onclick_mce');
which you install in your functions.php file in Wordpress. You can see it in action by toggling the text and visual view on the edit page. Without the extended list, the onclick goes away. With it, it remains.
You can solve this by changing the anchor tag into button and adding a script. For more info please refer to this link: Wordpress TinyMCE Strips OnClick & OnChange (need jQuery).
By resolving, I'm assuming you mean to allow the onclick attribute. You will want to be careful with this, because modifying the allowed tags does this for all your users.
You can modify the list of allowed tags and attributes, by adding this to your functions.php file:
function allow_onclick_content() {
global $allowedposttags, $allowedtags;
$newattribute = "onclick";
$allowedposttags["a"][$newattribute] = true;
$allowedtags["a"][$newattribute] = true; //unnecessary?
}
add_action( 'init', 'allow_onclick_content' );
I suggest trying it with only $allowedposttags first to see if that works for you. According to this other stackexchange post, you should only need allowedtags if you need it for comments or possibly non-logged-in users, but when I did something similar in the past, I needed both of them to work.
On a side note, if you want a list of all already allowed tags and attributes, look inside your /wp-includes/kses.php file.
That title is probably a bit confusing so let me elaborate.
I'm using HTML_purifier to clean up user input, although in this case the only user who will be using it will be myself (its in password protected folders). A long story short I would like to be able to add in image tag code to a web form, then on the page that it sends too use the code to display said image.
However i need the image tag to have css attributes added to it, one of which is
display:block
Anyway by default HTML_purifier removes this, detailed here because of the CSS.allowTricky option. As i understand it if you set the CSS.allowTricky option to True, then it should allow
display:block
However after doing this its still removing it, just wondering if anybody has done this before as i can't find much documentation about it on the web? Its not generating any errors in syslog, so im assuming that its the correct implementation but isn't working as expected.
My code at the moment.
include('HTMLPurifier.standalone.php');
$config = HTMLPurifier_Config::createDefault();
$config->set('CSS.AllowTricky', true);
* UPDATE **
The code should pass the config object (which the code already set) to the html purifier object. Putting it together it should look something like this.
include('HTMLPurifier.standalone.php');
$config = HTMLPurifier_Config::createDefault();
$config->set('CSS.AllowTricky', true);
$purifier = new HTMLPurifier($config);
Duplicate of http://htmlpurifier.org/phorum/read.php?3,6724 (solution was passing the config object to the HTML Purifier object so that the config actually got applied.)
For some reason, it seems like IE9 (I believe IE8 too, but not sure), is injecting
<SCRIPT LANGUAGE=VBScript>on error resume next pluginFound = IsObject(CreateObject("DIFFERENT PLUGIN EVERY TIME"))
in the middle of my content without any regards to surrounding context. This means it gets added in the middle of an attribute, or in the middle of some JavaScript, causing the HTML to be malformed and causing all sorts of problems.
This happens on multiple computers with different plugins, so it's not machine specific. And it's also not consistent: the location in which the offending script gets injected varies, the offending script varies. Sometimes you'll get several page loads without a problem and then you'll get the broken HTML.
My page is using a fair amount of JS, but nothing crazy. It's currently using jQuery, Google Maps, Bootstrap, Google Tag Manager, and loading a couple of Twitter, Google+, Facebook Iframes with their own little JS snippets. So, there are some asynchronous callbacks happening, but I wouldn't think this would interfere with how the browser renders the DOM and when it decides to inject plugin code.
You can see the problem if you reload http://www.rew.ca/properties/search/839721 enough times. If you scroll to the bottom of the page, you'll see raw JSON, or sometimes just some random HTML snippet will show in the middle of the page (because of mismatched tags).
Any ideas of why these scripts get injected arbitrarily and how to work around that?
Thanks
[UPDATE]
Here's another example of the script tags getting included in the middle of HTML content:
In my opinion, the problem lies in the http://cn.clickable.net/js/cct.js script, and specifically in the IsIEPlugin method of the __cct_tracker class:
this.IsIEPlugin = function (e) {
var t = !1;
return document.write('<SCRIPT LANGUAGE=VBScript>\n on error resume next \n pluginFound = IsObject(CreateObject("' + e + '")) </SCR' + "IPT>\n"), t ? 1 : 0
}
This method is called several times, with different arguments:
this.pixelRequestParams.cctDir = this.IsIEPlugin("SWCtl.SWCtl.1"),
this.pixelRequestParams.cctFlashPlugin = this.IsIEPlugin("ShockwaveFlash.ShockwaveFlash.1");
if (this.IsIEPlugin("PDF.PdfCtrl.1") == 1 ||
this.IsIEPlugin("PDF.PdfCtrl.5") == 1 ||
this.IsIEPlugin("PDF.PdfCtrl.6") == 1)
this.pixelRequestParams.cctPdf = 1;
this.pixelRequestParams.cctQuickTime = this.IsIEPlugin("Quicktime.Quicktime"),
this.pixelRequestParams.cctRealPlayer = this.IsIEPlugin("rmocx.RealPlayer G2 Control.1"),
this.pixelRequestParams.cctWmPlayer = this.IsIEPlugin("wmplayer.ocx")
I suppose (even I'm not sure) that "cct" stands for "Clickable Conversion Tracking", so it must be some sort of tracking code.
After further investigations, I've determined that the "cct.js" script gets loaded by the Google Tag Manager (GTM) script http://www.googletagmanager.com/gtm.js.
So, if I'm not wrong, by removing the GTM code snippet from your HTML page, you should be able to solve the problem.
It seems that the VBSCRIPT code dynamically injected by the GTM JavaScript code sometimes is not executed, but don't ask me why, since I don't really know.
I'm currently trying to build a new website, nothing special, nice and small, but I'm stuck at the very beginning.
My problems are clean URLs and page navigation. I want to do it "the right way".
What I would like to have:
I use CodeIgniter to get clean URLs like
"www.example.com/hello/world"
jQuery helps me using ajax, so I can
.load() additional content
Now I want to use HTML5 features like pushstate to
get rid of the # in the URL
It should be possible to go back and forth without a page refresh but the page will still display the right content according to the current URL.
It should also be possible to reload a page without getting a 404 error. The site should exist thanks to CodeIgniter. (there is a controller and a view)
For example:
A very basic website. Two links, called "foo" and "bar" and a emtpy div box beneath them.
The basic URL is example.com
When you click on "foo" the URL changes to "example.com/foo" without reloading and the div box gets new content with jQuery .load(). The same goes for the other link, just of course different content and URL.
After clicking "foo" and then "bar" the back button will bring me back to "example.com/foo" with the according content. If I load this link directly or refresh the page, it will look the same. No 404 error or something.
Just think about this page and tell me how you would do this.
I would really love to have this kind of navigation and so I tried several things.
So far...
I know how to use CodeIgniter to get the URLs like this. I know how to use jQuery to load additional content and while I don't fully understand the html5 pushstate stuff, I at least got it to work somehow.
But I can't get it to work all together.
My code right now is a mess, that's the reason I don't really want to post it here. I looked at different tutorials and copy pasted some code together. Would be better to upload my CI folder I guess.
Some of the tutorials I looked at:
Dive into HTML5
HTML5 demos
Mozilla manipulating the browser history
Saner HTML5 history
Github: History.js
(max. number of links reached :/)
I think my main problem is, that everybody tries to make it compatible with all browsers and different versions, adds scripts/jQuery plugins and whatnot and I get confused by all the additional code. There is more code between my script-tags then actual html content.
Could somebody post the most basic method how to use HTML5 for my example page?
My failed attemp:
On my test page, when I go back, the URL changes, but the div box will still show the same content, not the old one. I also don't know how to change the URL in the script according to the href attribute from the link. Is there something like $(this).attr('href'), that changes according to which link I click? Right now I would have to use a script for every link, which of course is bad.
When I refresh the site, CodeIgniter kicks in and loads the view, but really only the view by itself, the one I loaded with ajax, not the whole page. But I guess that should be easy to fix with a layout and the right controller settings. Haven't paid much attention to this yet.
Thanks in advance for any help.
If you have suggestions, ideas, or simple just want to mention something, please let me know.
regards
DiLer
I've put up a successful minimal example of HTML5 history here: http://cairo140.github.com/html5-history-example/one.html
The easiest way to get into HTML5 pushstate in my opinion is to ignore the framework for a while and use the most simplistic state transition possible: a wholesale replacement of the <body> and <title> elements. Outside of those elements, the rest of the markup is probably just boilerplate, although if it varies (e.g., if you change the class on HTML in the backend), you can adapt that.
What a dynamic backend like CI does is essentially fake the existence of data at particular locations (identified by the URL) by generating it dynamically on the fly. We can abstract away from the effect of the framework by literally creating the resources and putting them in locations through which your web server (Apache, probably) will simply identify them and feed them on through. We'll have a very simple file system structure relative to the domain root:
/one.html
/two.html
/assets/application.js
Those are the only three files we're working with.
Here's the code for the two HTML files. If you're at the level when you're dealing with HTML5 features, you should be able to understand the markup, but if I didn't make something clear, just leave a comment, and I'll walk you through it:
one.html
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<script src="assets/application.js"></script>
<title>One</title>
</head>
<body>
<div class="container">
<h1>One</h1>
Two
</div>
</body>
</html>
two.html
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<script src="assets/application.js"></script>
<title>Two</title>
</head>
<body>
<div class="container">
<h1>Two</h1>
One
</div>
</body>
</html>
You'll notice that if you load one.html through your browser, you can click on the link to two.html, which will load and display a new page. And from two.html, you can do the same back to one.html. Cool.
Now, for the history part:
assets/application.js
$(function(){
var replacePage = function(url) {
$.ajax({
url: url,
type: 'get',
dataType: 'html',
success: function(data){
var dom = $(data);
var title = dom.filter('title').text();
var html = dom.filter('.container').html();
$('title').text(title);
$('.container').html(html);
}
});
}
$('a').live('click', function(e){
history.pushState(null, null, this.href);
replacePage(this.href);
e.preventDefault();
});
$(window).bind('popstate', function(){
replacePage(location.pathname);
});
});
How it works
I define replacePage within the jQuery ready callback to do some straightforward loading of the URL in the argument and to replace the contents of the title and .container elements with those retrieved remotely.
The live call means that any link clicked on the page will trigger the callback, and the callback pushes the state to the href in the link and calls replacePage. It also uses e.preventDefault to prevent the link from being processed the normal way.
Finally, there's a popstate event that fires when a user uses browser-based page navigation (back, forward). We bind a simple callback to that event. Of note is that I couldn't get the version on the Dive Into HTML page to work for some reason in FF for Mac. No clue why.
How to extend it
This extremely basic example can more or less be transplanted onto any site because it does a very uncreative transition: HTML replacement. I suggest you can use this as a foundation and transition into more creative transitions. One example of what you could do would be to emulate what Github does with the directory navigation in its repositories. It's an intermediate manoever that requires floats and overflow management. You could start with a simpler transition like appending the .container in the loaded page to the DOM and then animating the old container to {height: 0}.
Addressing your specific "For example"
You're on the right track for using HTML5 history, but you need to clarify your idea of exactly what /foo and /bar will contain. Basically, you're going to have three pages: /, /foo, and /bar. / will have an empty container div. /foo will be identical to / except in that container div has some foo content in it. /bar will be identical to /foo except in that the container div has some bar content in it. Now, the question comes to how you would extract the contents of the container through Javascript. Assuming that your /foo body tag looked something like this:
<body>
foo
bar
<div class="container">foo</div>
</body>
Then you would extract it from the response data through var html = $(data).filter('.container').html() and then put it back into the parent page through $('.container').html(html). You use filter instead of the much more reasonable find because from some wacky reason, jQuery's DOM parser produces a jQuery object containing every child of the head and every child of the body elements instead of just a jQuery object wrapping the html element. I don't know why.
The rest is just adapting this back into the "vanilla" version above. If you are stuck at any particular stage, let me know, and I can guide you better though it.
Code
https://github.com/cairo140/html5-history-example
Try this in your controller:
if (!$this->input->is_ajax_request())
$this->load->view('header');
$this->load->view('your_view', $data);
if (!$this->input->is_ajax_request())
$this->load->view('footer');
I'm trying to restraint editing on the Wiki (using MediaWiki) that I'm creating as an internal project for my company.
We would like to be able to let the page creators specify none or one of the two following options:
Nobody besides the creator of this page can edit the content of this page
Anybody can edit the content of this page, but there must be an approval by the page creator before the changes are visible (whether it'd be by mail, on the wiki directly or something else - does not matter).
If the creator does not specify any of the 2 options, anybody can edit the page, and the changes are immediatly visible (default behaviour).
I've been browsing the net but I did not find an out-of-the-box solution for this. We managed to make some great custom stuff thanks to the edition of the LocalSettings file but not this.
Is there a solution for that functionality?
I don't know of an extension that would make this easy.
What I think you could do would be to take an extension like Flagged Revs or Approved Revs and make it so that instead of using groups as the determiner of approval status, it uses username. This might not be too difficult. Does this make sense?
I had the same problem as you and now i fixed it, here is the solution:
I am using http://www.mediawiki.org/wiki/Extension%3aApproved_Revs for article protection but it didn't fulfil my need it allowed the user to change the currently approved revision of the article and so the change was immediately reflected on the main page so I hacked it a bit, basically you need only one change
go to ApprovedRevs/ApprovedRevs.hooks.php
and find the following code:
static public function setLatestAsApproved( &$article , &$user, $text,
$summary, $flags, $unused1, $unused2, &$flags, $revision,
&$status, $baseRevId ) {
this is a function declaration just after it add the following code:
return false;
and it will work the way you wanted it to be i.e (the change you did will not be reflected until you approve it)