DOMDocument createComment function doesn't work - xpath

I'm trying to create a comment inside a new <div> using XPath and DOMDocument.
Here's the process that I'm using:
I'm looking for a script tag using XPath in my DOM, then I loop the results and trying to create a new element using DOMDocument and insert it:
$xpath = new DOMXPath( $dom );
$scripts = $xpath->query( '//script[#src[contains(., "//cdn.chitika.net/getads.js" )]]' );
foreach ( $scripts as $script ) {
$external_tag = $dom->createElement( 'div' );
$external_tag->setAttribute( 'data-lazy-widget', null );
$external_tag->appendChild( $dom->createComment( 'Hello World' ) );
$script->parentNode->insertBefore( $external_tag, $script );
}
It sets the attribute and inserts it before the $script node well, but in the DOM just shows an empty <div>.
<div data-lazy-widget> </div>
So, I think $dom->createComment( 'Hello World' ) doesn't work, or maybe I'm doing something wrong?
What can I do?

Related

Simple Dom Parser Returns Empty via Ajax

I'm using Simple HTML Dom Parser to correct some links in my output to good effect but have found some strange behaviour when calling content via Ajax. I'm using the parser on a WordPress site so feed the $content variable into the following function:
function add_trailing_slash( $content ) {
$content = str_get_html( $content );
if( $content ):
foreach( $content->find('a') as $a ):
if( isset( $a->href ) && '' !== $a->href && '#' !== $a->href ):
// replace http with https on all link hrefs
$a->href = str_replace('http:', 'https:', $a->href);
// checks if link lacks trailing slash and appends it if no extension (file)
$ext = pathinfo( $a->href, PATHINFO_EXTENSION );
if( '/' !== substr( $a->href, -1 ) && ! $ext ) $a->href = $a->href . '/';
endif;
endforeach;
endif;
return $content;
}
This is working great when added to the_content filter with add_filter( 'the_content', 'add_trailing_slash' ) and even when called directly like return add_trailing_slash( $output ) however, when I call the same function via Ajax I get a 'success' response but which is completely empty. Stranger still, I found that if I return the output via wpautop( $output ) it comes back just fine. wpautop (link) is essentially a bunch of preg_replace functions to replace double line breaks with <p> tags so I tested returning my output via return preg_replace('<blah>', '', $content) and it worked!
Oh, I also tested removing all my changes from the add_trailing_slash() function above and the same issue persisted so I guess that something to do with the way str_get_html( $content ) parses the input makes it not play well with the Ajax callback. But why does preg_replace make it returnable?
function add_trailing_slash( $content ) {
$content = str_get_html( $content );
return $content;
}
I'm wondering if anyone else has come across this issue, whether I'm missing something and this is expected or whether this is a bug? I could leave in my preg_replace which appears to 'fix' the issue but it feels like something of a hack.
The only thing that come to my mind is that when you do $content = str_get_html( $content ); you are getting an object as result. Maybe when it goes through wp functions it get interpreted like a string but when you are json_encoding it, something may go wrong and kill it. You can either try to force-cast it to string with
return (string) $content;
or try to use
// Dumps the internal DOM tree back into string
$str = $html->save();
as described in the docs

how to put <b> tag in string in smarty template

I am using SMARTY and I need to put <b> tag in string in the following php code i can put tag in string
$search = 'this is my sample strangا';
$dbContent = 'this strang is for sample hello world';
$search = explode( ' ' , $search );
function wrapTag($inVal){
return '<b>'.$inVal.'</b>';
}
$replace = array_map( 'wrapTag' , $search );
$dbContent = str_replace( $search , $replace , $dbContent );
echo $dbContent;
how to use this code in smarty template or how to convert this code for smarty
In my opinion there's no need put such code into Smarty template, so the only thing you should do is
$smarty->assign('dbContent', $dbContent);
and in Smarty template file:
{$dbContent}
You should separate logic and display. In this case you shouldn't rather move this code to Smarty. If Your wrapTag function contained a lot of HTML you could do it this way ( I know global is not nice solution but probably it could be done also in the other way):
function wrapTag($inVal){
global $smarty;
$smarty->assign('inVal', $inVal);
return $smarty->fetch('bold_template.tpl');
}
and inside bold_template.tpl you could have:
<b>{$inVal}</b>
But if you only add <b> tags there's no point to put it in Smarty template

CKEditor Inlineditor - Select by class instead of ID

So I have a page with several textareas for a custom form I made. I am able to target an individual textarea by it's ID but I would like to know if theres an easy way to have the CKeditor inline target all textareas elements or have editor select elements by their class instead. At the moment I have setup ID for each other but they are each unique, trying to figure out the best aproach but im not good with javascript and would like some assistance with this.
Current code:
<script>
CKEDITOR.inline( 'ID');
</script>
Looking for a code that would target all text areas or at lease target class instead of IDs.
Use CKEDITOR.document.find:
var elements = CKEDITOR.document.find( '.foo' ),
i = 0,
element;
while ( ( element = elements.getItem( i++ ) ) ) {
CKEDITOR.inline( element );
}
You can also use the official jQuery adapter:
$( '.foo' ).ckeditor( function() {
// Callback function code.
}, {
// Config options here
} );
You can use this:
$(".ckeditor").each(function () {
CKEDITOR.replace( $(this).attr("name") );
});
This sample shows how to automatically replace all <textarea> elements of a given class with a CKEditor instance.
To replace a <textarea> element, simply assign it the ckeditor class, as in the code below:
<script src="https://cdn.ckeditor.com/4.11.4/standard/ckeditor.js"></script>
<textarea class="ckeditor" name="editor1"></textarea>
<textarea class="ckeditor" name="editor2"></textarea>
<textarea class="" name="editor3"></textarea>
Note that other attributes (like id or name) need to be adjusted to your document.
ckeditor replacebyclass

Toggle Class Prototype Function

I'm trying to iterate over an array of elements, specified by class name. Then I want to use a function to toggle the class and change some text.
This does NOT work:
$$('.btn').forEach( setButtonLoadingStateOn, this );
setButtonLoadingStateOn = function( btn ) {
btn.toggleClassName('loading');
btn.disable();
btn.select('span span')[0].update( "please wait..." );
}
This does NOT work:
$$('.btn').each( function(btn) {
btn.addClassName('loading');
btn.disable();
btn.select('span span')[0].innerHTML = "please wait...";
});
This also does NOT work:
setButtonLoadingState( '.btn', 'start' );
setButtonLoadingState = function( btnClass, loadState ) {
btnElem = $$( btnClass );
btnElem.each(function( el ){
if ( loadState == 'start' ) {
el.addClassName( 'loading' );
el.disable();
el.select('span span')[0].innerHTML = "please wait...";
} else {
el.removeClassName( 'loading' );
el.enable();
el.select('span span')[0].innerHTML = "buy now";
}
});
}
If I console.log() the element, I get the object (or array) I'm expecting, so I don't know what's wrong.
I've also tried several SO answers, including this one: Add or remove class with prototype
In case it matters, the platform is Magento CE 1.8.0.2. How can I update these button elements using Prototype? Thanks.
~ edit ~
There are several HTML elements on the page. They all look like this:
<button type="button" title="buy now" class="button btn" onclick="productAddToCart(this)">
<span><span>Quick Buy</span></span>
</button>
Thanks so much to all who contributed. The AJAX request was returning a hyphenated key in the JSON response:
{"msg-html":"blah blah blah"}
Reading this from the response object as follows was the problem:
var ajaxResult = transport.responseText.evalJSON();
var ajaxMsg = ajaxResult.msg-html;
Hyphens are not allowed in JSON keys, instead the object needs to be accessed as follows:
var ajaxMsg = ajaxResult["msg-html"];
... or remove the hyphens! Thanks again to all.
Full credit to this dude/dudette: http://developer.appcelerator.com/question/120227/parsing-json-with-hyphenated-key-names

strict with CGI::AJAX

I have set of code for updating a password in the table, here I'm using CGI::AJAX module to update the password and get the popup screen on corresponding execution.When using that code with my application it is executing properly but I didn't get the output(means Perl subroutine is not called when JavaScript function to get use.password is not updated into table). I don't get any error either.
#!/usr/bin/perl -w
use strict;
use CGI;
use DBI;
use Data::Dumper;
my $p = new CGI qw(header start_html end_html h1 script link);
use Class::Accessor;
use CGI::Ajax;
my $create_newuser;
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
print $ajax->build_html($p,\&Show_html,{-charset=>'UTF-8', -expires=>'-1d'});
sub Show_html
{
my $html = <<EOHTML;
<html>
<body bgcolor="#D2B9D3">
<IMG src="karvy.jpg" ALT="image">
<form name='myForm'>
<center><table><tr><td>
<div style="width:400px;height:250px;border:3px solid black;">
<center><h4>Create New Password's</h4>
<p>&nbsp User Name</b>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<INPUT TYPE="text" NAME="user" id = "user" size = "15" maxlength = "15" tabindex = "1"/></p>
<p>&nbsp Password:</b>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<INPUT TYPE=PASSWORD NAME="newpassword" id = "newpassword" size = "15" maxlength = "15" tabindex = "1"/></p>
<p>&nbsp Re-Password:</b>&nbsp&nbsp&nbsp<INPUT TYPE=PASSWORD NAME="repassword" id = "repassword" size = "15" maxlength = "15" tabindex = "1"/></p>
<input type="submit" id="val" value="Submit" align="middle" method="GET" onclick="fetch_javaScript(['user','newpassword','repassword']);"/><INPUT TYPE="reset" name = "Reset" value = "Reset"/>
<p>Main Menu <A HREF = login.pl>click here</A>
</center>
</div>
</td></tr></table></center>
</form>
</body>
</html>
EOHTML
return $html;
}
$create_newuser =sub
{
my #input = $p->params('args');
my $user=$input[0];
my $password=$input[1];
my $repassword=$input[2];
my $DSN = q/dbi:ODBC:SQLSERVER/;
my $uid = q/123/;
my $pwd = q/123/;
my $DRIVER = "Freetds";
my $dbh = DBI->connect($DSN,$uid,$pwd) or die "Coudn't Connect SQL";
if ($user ne '')
{
if($password eq $repassword)
{
my $sth=$dbh->do("insert into rpt_account_information (user_id,username,password,user_status,is_admin) values(2,'".$user."','".$password."',1,1)");
my $value=$sth;
print $value,"\n";
if($value == 1)
{
print 'Your pass has benn changed.Return to the main page';
}
}
else
{
print "<script>alert('Password and Re-Password does not match')</script>";
}
}
else
{
print "<script>alert('Please Enter the User Name')</script>";
}
}
my $create_newuser;
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
...;
$create_newuser =sub { ... };
At the moment when you create a new CGI::Ajax object, the $create_newuser variable is still undef. Only much later do you assign a coderef to it.
You can either assign the $create_newuser before you create the CGI::Ajax:
my $create_newuser =sub { ... };
my $ajax = new CGI::Ajax('fetch_javaScript' => $create_newuser);
...;
Or you use a normal, named subroutine and pass a coderef.
my $ajax = new CGI::Ajax('fetch_javaScript' => \&create_newuser);
...;
sub create_newuser { ... }
Aside from this main error, your script has many more problems.
You should use strict instead of the -w option.
For debugging purposes only, use CGI::Carp 'fatalsToBrowser' and sometimes even with warningsToBrowser can be extremely helpful. Otherwise, keeping a close eye on the error logs is a must.
my $p = new CGI qw(header start_html end_html h1 script link) doesn't make any sense. my $p = CGI->new should be sufficient.
use Class::Accessor seems a bit random here.
The HTML in Show_html is careless. First, your heredocs allows variable interpolation and escape codes – it has the semantics of a double quoted string. Most of the time, you don't want that. Start a heredoc like <<'END_OF_HTML' to avoid interpolation etc.
Secondly, look at that tag soup you are producing! Here are some snippets that astonish me:
bgcolor="#D2B9D3", align="middle" – because CSS hasn't been invented yet.
<center> – because CSS hasn't been invented yet, and this element isn't deprecated at all.
<table><tr><td><div ... </div></td></tr></table> – because there is nothing wrong with a table containing a single cell. (For what? This isn't even for layout reasons!) This table cell contains a single div …
… which contains another center. Seriously, what is so great about unneccessary DOM elements that CSS isn't even an option.
style="width:400px;height:250px;border:3px solid black;" – because responsive design hasn't been invented yet.
<p> ... </b> – Oh, what delicious tag soup!
&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp – this isn't a typewriter, you know. Use CSS and proper markup for your layout. There is a difference between text containing whitespace, and empty areas in your layout.
tabindex = "1" … tabindex = "1" … tabindex = "1" – I don't think you know what tabindex does.
<A HREF = login.pl> – LOWERCASING OR QUOTING YOUR ATTRIBUTES IS FOR THE WEAK!!1
onclick="fetch_javaScript(['user','newpassword','repassword']);" – have you read the CGI::Ajax docs? This is not how it works: You need to define another argument with the ID of the element where the answer HTML is displayed.
In your create_newuser, you have an SQL injection vulnerability. Use placeholders to solve that. Instead of $sth->do("INSERT INTO ... VALUES('$foo')") use $sth->do('INSERT INTO ... VALUES(?)', $foo).
print ... – your Ajax handler shouldn't print output, instead it should return a HTML string, which then gets hooked into the DOM at the place your JS function specified. You want something like
use HTML::Entities;
sub create_newuser {
my ($user, $password, $repassword) = $p->params('args');
my ($e_user, $e_password) = map { encode_entities($_) } $user, $password;
# DON'T DO THIS, it is a joke
return "Hello <em>$e_user</em>, your password <code>$e_password</code> has been successfully transmitted in cleartext!";
}
and in your JS:
fetch_javaScript(['user','newpassword','repassword'], ['answer-element'], 'GET');
where your HTML document somewhere has a <div id="answer-element" />.

Resources