target html class and fill with content DOMdocument - xpath

I am aiming to fill an html element of a certain std html class with content
This answer has a pretty complex concat xpath query:
Using DOMDocument to extract from HTML document by class
This class extension will get and fill html nicely:
https://gist.github.com/j0shua/945507
This is the example html i am working with:
<!-- actual content of the page box -->
<div class="masterWidthSet mainContent">
<div class="mainPageContent">
<script type="text/javascript" src="/email_js.js"></script>
<b>Contact us all at the same time...</b><br/>
<div class="messageSent">Thank you for contacting us, we will get back to you as soon as possible.</div>
<table class="contactForm">
<tr><td class="title">Name</td><td class="description"><input type="text" id="sendName" class="text" placeholder="Your name..."></td></tr>
<tr><td class="title">Number (optional)</td><td class="description"><input type="text" id="phoneNo" class="text"placeholder="Your number..."></td></tr>
<tr><td class="title">Email</td><td class="description"><input type="text" id="email" class="text"placeholder="Your email..."></td></tr>
<tr><td class="title">Message</td><td class="description"><textarea id="message" class="text"placeholder="Your message..."></textarea></td></tr>
<tr><td></td><td class="description"><input type="button" class="submit" value="Send us you message..." onclick="sendMessage()"/><span class="description messageStatus" id="messageStatus"></span></td></tr>
</table>
</div>
</div>
I can easily get the innHTML of the element with a single class 'mainPageContent':
require_once WEBROOT_PRIVATE.'scripts/JSLikeHTMLElement.php';
$dom = new \DOMDocument();
$dom->registerNodeClass('DOMElement', 'JSLikeHTMLElement');
$dom->loadHTML( file_get_contents( $file['local_path'] ) );
$xpath = new \DOMXPath($dom);
$elem = $xpath->query('//*[#class="mainPageContent"]')->item(0);
echo $elem->innerHTML;
But as soon as i try to target a element with multiple classes it returns null (i am assuming because the query is looking for a an exact match) eg 'mainContent':
$elem = $xpath->query('//*[#class="mainContent"]')->item(0);
So I tried to use the concat query from the top post but i get 'Call to a member function item()':
$elem = $xpath->query("//*[contains(concat(' ', normalize-space(#class), ' '), ' mainContent ')")->item(0);
So i tried this:
$elem = $xpath->query('//*[class~="mainContent"]')->item(0);
The problem is each time the item(0) results in an error:
Call to a member function item() on a non-object
This guy says the ways i tried should work.. Selecting a css class with xpath
Can anyone point me in the right direction?
Thanks,
J

Scrap all of the above and just use the phpquery library.
Just like jquery for php! bish bash bosh.
http://code.google.com/p/phpquery/

Related

Angular 2 doesn't update my view after I add or edit item

I've finally made my app in angular 2. Everything is solved, except one thing. When I add item into my table or edited it, I can't see the change until I refresh page or click for example next page button (I have implemented pagination). I included:
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
in this order. My method for adding item is very simple:
addDepartment(item){
this._departmentService.addDepartment(item)
.subscribe(departments => this.department = departments.json());
this.getAll();}
Whhen I add item, and put breakpoint on get method, It is called correctly and I get right information from my DB, but I don't know why view isn't refreshed then. Do you have any idea why is it happened? Thanks for suggestions!
EDIT: department is just department: Department, where Department is interface with properties (departmentNo, departmentName, departmentLocation). The view for adding item looks like:
<form [ngFormModel]="myForm"
(ngSubmit)="addDepartment(newItem); showAddView=false" [hidden]="!showAddView" align="center">
<div>
<label for="editAbrv">Department name:</label><br>
<input type="text" [(ngModel)]="newItem.departmentName" [ngFormControl]="myForm.controls['departmentName']" >
<div *ngIf="myForm.controls['departmentName'].hasError('required')" class="ui error message"><b style="color:red;">Name is required</b></div>
</div>
<br/>
<div>
<label for="editAbrv">Department Location:</label><br>
<input type="text" [(ngModel)]="newItem.departmentLocation" [ngFormControl]="myForm.controls['departmentLocation']" >
<div *ngIf="myForm.controls['departmentLocation'].hasError('required')" class="ui error message"><b style="color:red;">Location is required</b></div>
</div>
<br/>
<div>
<button type="submit" [disabled]="!myForm.valid" class="ui button">Add item</button>
<button><a href="javascript:void(0);" (click)="showHide($event)" >
Cancel
</a></button>
</div>
</form>
and my department table is:
<table align="center">
<thead>
<tr>
<td>#</td>
<td><strong>Department</strong></td>
<td><strong>Department Location</strong></td>
<td><strong>Edit</strong></td>
<td><strong>Delete</strong></td>
</tr>
</thead>
<tbody>
<tr *ngFor="#department of departments | searchString:filter.value ; #i = index">
<td>{{i + 1}}.</td>
<td> {{department.departmentName}}</td>
<td>{{department.departmentLocation}}</td>
<td>
<button class="btnEdit" (click)="showEdit(department)">Edit</button>
</td>
<td>
<button class="btnDelete" (click)="deleteDepartment(department)" >Delete</button>
</td>
</tr>
</tbody>
</table>
With this code, you don't wait for the response of the addDepartment request and execute the getAll request directly.
addDepartment(item){
this._departmentService.addDepartment(item)
.subscribe(departments => this.department = departments.json());
this.getAll();
}
You should move the call to getAll within the callback registered in subscribe. At this moment, the addDepartment is actually done and you can reload the list...
The code could be refactored like this (it's a guess since I haven't the content of addDepartment and getAll methods):
addDepartment(item){
this._departmentService.addDepartment(item)
.subscribe(addedDepartment => {
this.department = this.getAll();
});
}
This issue occurs because of the way you're using departmant and how change detection works. When you use *ngFor="#department of departments", angular change detection looks for a object reference on departments array. When you update/change one of the items in this array object reference to the array itself doesn't change, so angular doesn't run change detection.
You have few options:
1) change reference of the array by replacing it with new array with updated values
2) tell angular explicitly to run change detection (which I think is easier in your case):
constructor(private _cdRef: ChangeDetectorRef) {...}
addDepartment(item){
this._departmentService.addDepartment(item)
.subscribe(departments => this.department = departments.json());
this.getAll();
this._cdRef.markForCheck();
}

getelementbyclassname instead of getelementbyid is not working

I have read many times that you can NOW get getElementsByClassName. This below works fine IF I replace ClassName by Id, but using the word ClassName does not work. Anyone know why? (I tried on Chrome and Firefox)
<script type="text/javascript">
function makeDisable(){
var x=document.getElementsByClassName("mySelect");
x.disabled=true
}
function makeEnable(){
var x=document.getElementsByClassName("mySelect");
x.disabled=false
}
</script>
<form>
<select class="mySelect" id="mySelect">
<option>Apple</option>
<option>Banana</option>
<option>Orange</option>
</select>
<input type="button" onclick="makeDisable()" value="Disable list">
<input type="button" onclick="makeEnable()" value="Enable list">
</form>
The function is called getElementsByClassName. Plural. It returns not an element, but an array of all the elements that have the class name.
So even if the array consists of only one item, even there is only one element in the array, you still need to index it.
x[0].disabled=true
instead of
x.disabled=true
Fiddle

getElementById and innerText only changes one, not all

I have searched up and down for days, no luck. Please help. This projec will only be used in IE7, it has a text box that you enter your name, and onclick should populate that name into all the spans. this is where I am at, but it only changes the first span.
Please Help. Thank you.
<form>
<input id="i" value="My_Name">
<input type="button" value="Enter"
onClick="document.getElementById('initials').innerText= i.value;">
</form>
<span id="initials">name</span>
<br />
<span id="initials">name</span>
<br />
<span id="initials">name</span>
<br />
<span id="initials">name</span>
An element's id should be unique in the document. You cannot use the same id for multiple elements. Some options:
Give the elements different IDs and retrieve them independently using multiple invocations of getElementById
Retrieve the elements by tag name using getElementsByTagName and loop over the results. (Consider wrapping the common span elements in a div and selecting by tag name relative to that wrapper.)
Give the elements a common class name and use some implementation of getElementsByClassName to retrieve the results
Give the elements a common value for the name attribute (which does not need to be unique) and use getElementsByName.
The rule is that id should be different where you are using same initials id for all span elements. You can give them different ids and try like this:
document.getElementById('initials1').innerText= i.value;
document.getElementById('initials2').innerText= i.value;
document.getElementById('initials3').innerText= i.value;
document.getElementById('initials4').innerText= i.value;
So you can modify your html like this:
<span id="initials1">name</span>
<br />
<span id="initials2">name</span>
<br />
<span id="initials3">name</span>
<br />
<span id="initials4">name</span>
And
<form>
<input id="i" value="My_Name">
<input type="button" value="Enter" onClick="doIt();">
</form>
JS:
function doIt(){
document.getElementById('initials1').innerText= i.value;
document.getElementById('initials2').innerText= i.value;
document.getElementById('initials3').innerText= i.value;
document.getElementById('initials4').innerText= i.value;
}
If you don't want to use ids, you can use getElementsByTagName and change function like this:
function doIt(){
var spans = document.getElementsByTagName('span');
for(var i = 0; i < spans.length; i++){
spans[i].innerText = document.getElementById('i').value;
}
}

Undefined Index for $_POST (noob question!) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
PHP: “Notice: Undefined variable” and “Notice: Undefined index”
I am just learning PHP and I keep getting an Undefined Index error. The book I'm learning from has an HTML form and a PHP page that processes the form, using the following format:
<!-- The form fields are all set up something like this -->
<input type="text" id="howlong" name="howlong" /><br />
// The PHP starts with one line like this for each of the form fields in the HTML
$how_long = $_POST ['howlong'];
// And there is one line for each one like this to output the form data:
echo ' and were gone for ' . $how_long . '<br />';
The example I'm working with has about 12 form fields.
What's odd is that not all of the variables throw this error, but I can't see a pattern to it.
I've checked that all HTML fieldnames match up with the PHP $_POST variable name I entered, and I've made certain that when I fill out the form and submit it that all fields are filled in with something. Interestingly, the completed code that can be downloaded for the book also throws this error.
I realize this code may not reflect best practices, it's from the first chapter of the book and obviously I am a noob :)
In case it makes a difference, I am using PHP 5.3.5 on XAMPP 1.7.4 with Windows 7 Home Premium.
Remember to set the method to POST on the form tag...
heres the code i used to try yours, and it worked to me:
in a file named test.php:
<html>
<body>
<form method="POST" action="testProc.php">
<input type="text" id="howlong" name="howlong" /><br/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
and in testProc.php:
<?php
if (isset($_POST)) {
if (isset($_POST["howlong"])){
$howlong = $_POST['howlong'];
echo ' and were gone for ' . $howlong . '<br />';
}
}
?>
Just as an advise, to make display manipulation with stylesheets i recommend to put forms within a table, like this:
<html>
<body>
<form method="POST" action="testProc.php">
<table>
<tbody>
<tr>
<th>
<label for="howlong">How long? :</label>
</th>
<td>
<input type="text" id="howlong" name="howlong" />
</td>
</tr>
<tr>
<input type="submit" value="submit"/>
</tr>
</tbody>
</table>
</form>
</body>
</html>
Hope you can use this...
you need to check that form is submitted and then you can try to use $_POST array, so you should put this code above:
if(isset($_POST['send'])) {
where "send" is name of submit button
You can test to see if a variable is set using the isset() function.
Also, not all HTML form elements will post a value in all cases. The common example is the checkbox; an unchecked checkbox doesn't form part of the the data posted back to the server. Therefore the $_POST element you're expecting to be set won't be.

Dojo Table not Rendering in IE6

I'm trying to use Dojo (1.3) checkBoxes to make columns appear/hide in a Dojo Grid that's displayed below the checkBoxes. I got that functionality to work fine, but I wanted to organize my checkBoxes a little better. So I tried putting them in a table. My dojo.addOnLoad function looks like this:
dojo.addOnLoad(function(){
var checkBoxes = [];
var container = dojo.byId('checkBoxContainer');
var table = dojo.doc.createElement("table");
var row1= dojo.doc.createElement("tr");
var row2= dojo.doc.createElement("tr");
var row3= dojo.doc.createElement("tr");
dojo.forEach(grid.layout.cells, function(cell, index){
//Add a new "td" element to one of the three rows
});
dojo.place(addRow, table);
dojo.place(removeRow, table);
dojo.place(findReplaceRow, table);
dojo.place(table, container);
});
What's frustrating is:
Using the Dojo debugger I can see that the HTML is being properly generated for the table.
I can take that HTML and put just the table in an empty HTML file and it renders the checkBoxes in the table just fine.
The page renders correctly in Firefox, just not IE6.
The HTML that is being generated looks like so:
<div id="checkBoxContainer">
<table>
<tr>
<td>
<div class="dijitReset dijitInline dijitCheckBox"
role="presentation" widgetid="dijit_form_CheckBox_0"
wairole="presentation">
<input class="dijitReset dijitCheckBoxInput"
id="dijit_form_CheckBox_0"
tabindex="0" type="checkbox"
name="" dojoattachevent=
"onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick"
dojoattachpoint="focusNode" unselectable="on"
aria-pressed="false"/>
</div>
<label for="dijit_form_CheckBox_0">
Column 1
</label>
</td>
<td>
<div class="dijitReset dijitInline dijitCheckBox"
role="presentation" widgetid="dijit_form_CheckBox_1"
wairole="presentation">
<input class="dijitReset dijitCheckBoxInput"
id="dijit_form_CheckBox_1"
tabindex="0" type="checkbox"
name="" dojoattachevent=
"onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick"
dojoattachpoint="focusNode" unselectable="on"
aria-pressed="false"/>
</div>
</td>
</tr>
<tr>
...
</tr>
</table>
</div>
I would have posted to the official DOJO forums, but it says they're deprecated and they're using a mailing list now. They said if a mailing list doesn't work for you, use StackOverflow.com. So, here I am!
It looks like you forgot to create a <tbody> element.
I also encountered this issue when trying to generate a table using dojo in IE7. The html is there but nothing is rendered. Again, the solution is to use thead, tbody tags.

Resources