<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>HTML &#8211; Roy Duineveld</title>
	<atom:link href="https://royduineveld.nl/tag/html/feed/" rel="self" type="application/rss+xml" />
	<link>https://royduineveld.nl</link>
	<description>Waarom moeilijk doen als het makkelijk kan?</description>
	<lastBuildDate>Tue, 27 Jan 2026 07:48:00 +0000</lastBuildDate>
	<language>nl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.9.26</generator>
	<item>
		<title>Geavanceerd Bootstrap 3 gebruik</title>
		<link>https://royduineveld.nl/geavanceerd-bootstrap-3-gebruik/</link>
		<comments>https://royduineveld.nl/geavanceerd-bootstrap-3-gebruik/#respond</comments>
		<pubDate>Sat, 03 Jan 2015 13:35:39 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[LESS]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Twitter Bootstrap]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=718</guid>
		<description><![CDATA[<p>Bootstrap, een geweldig HTML, CSS en JS framework om snel en eenvoudig responsive websites mee te ontwikkelen. Echter hekelen veel mensen tegen het &#8220;probleem&#8221; dat de HTML &#8220;vervuild&#8221; wordt met...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/geavanceerd-bootstrap-3-gebruik/">Geavanceerd Bootstrap 3 gebruik</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Bootstrap, een geweldig HTML, CSS en JS framework om snel en eenvoudig responsive websites mee te ontwikkelen. Echter hekelen veel mensen tegen het &#8220;probleem&#8221; dat de HTML &#8220;vervuild&#8221; wordt met alle classes die nodig zijn voor de styling. Kan dat niet anders?</p>
<h2>Bootstrap 3 met <a title="LESS" href="http://lesscss.org/" target="_blank">LESS</a></h2>
<p>Dat kan zeker anders! Gebruik de <a title="Bootstrap LESS bestanden" href="http://getbootstrap.com/css/#less" target="_blank">LESS bestanden van Bootstrap</a>! LESS moet wél ge-compiled worden naar gewoon CSS, hiervoor zijn tal van plugins te vinden voor populaire systemen als <a title="LESS plugin voor WordPress" href="https://wordpress.org/plugins/wp-less/" target="_blank">WordPress</a> en <a title="LESS plugin voor Magento" href="http://www.magentocommerce.com/magento-connect/magemaven-lesscss.html" target="_blank">Magento</a>, maar nog handiger is <a title="Grunt" href="http://gruntjs.com/" target="_blank">Grunt</a> of <a title="Gulp" href="http://gulpjs.com/" target="_blank">Gulp</a>! Alleen door LESS te gebruiken ben je er natuurlijk niet, daarvoor zijn er in <a title="LESS mixins" href="http://lesscss.org/features/#mixins-feature" target="_blank">LESS mixins</a>! In de Bootstrap documentatie zie je op meerdere plekken voorbeelden staan met &#8220;Usage as a Mixin&#8221; als commentaar erbij. Hiermee kan je classes aan selectors hangen.</p>
<h3>Bootstrap classes aan CSS selectors</h3>
<p>Wanneer je een afbeelding ronde hoeken wilt geven heeft Bootstrap hier de &#8220;img-rounded&#8221; class voor, in de <a title="Bootstrap image shapes" href="http://getbootstrap.com/css/#images-shapes" target="_blank">documentatie</a> staat dat deze als volgt gebruikt kan worden:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;img src=&quot;...&quot; alt=&quot;...&quot; class=&quot;img-rounded&quot;&gt;
</pre>
<p>Wanneer je alle afbeeldingen op je website ronde hoeken wilt geven, kan dit middels LESS i.c.m. Bootstrap als volgt gedaan worden:</p>
<pre class="brush: css; title: ; notranslate">
img {
	.img-rounded();
}
</pre>
<p>Op die manier zijn de classes in de HTML niet nodig!</p>
<h3>Bootstrap Grid met mixins</h3>
<p>Niet alleen de &#8220;eenvoudige&#8221; dingen uit Bootstrap kunnen op deze manier gebruikt worden, maar ook bijvoorbeeld het <a title="Bootstrap grid i.c.m. LESS" href="http://getbootstrap.com/css/#grid-less" target="_blank">Bootstrap Grid</a>! Een stukje HTML als voorbeeld:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div class=&quot;container&quot;&gt;
	&lt;div class=&quot;menu&quot;&gt;&lt;/div&gt;
	&lt;div class=&quot;content&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Wanneer je van de container een row wilt maken en van menu en content een kolom dan kan je dit als volgt doen:</p>
<pre class="brush: css; title: ; notranslate">
.container {
	.make-row();

	.menu {
		.make-md-column(3);
	}

	.content {
		.make-md-column(9);
	}
}
</pre>
<blockquote><p>Een heel mooi voorbeeld waar dit gebruikt wordt is het <a href="https://github.com/webcomm/magento-boilerplate" title="Magento Boilerplate" target="_blank">Magento Boilerplate</a>!</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/geavanceerd-bootstrap-3-gebruik/">Geavanceerd Bootstrap 3 gebruik</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/geavanceerd-bootstrap-3-gebruik/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pijltjes op de collapse / accordion van Twitter Bootstrap</title>
		<link>https://royduineveld.nl/pijltjes-collapse-accordion-twitter-bootstrap/</link>
		<comments>https://royduineveld.nl/pijltjes-collapse-accordion-twitter-bootstrap/#comments</comments>
		<pubDate>Sun, 01 Sep 2013 14:09:21 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Twitter Bootstrap]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=515</guid>
		<description><![CDATA[<p>Recent kreeg ik feedback op een website die ik in het verleden gemaakt had waarbij de collapse van Twitter Bootstrap gebruikt wordt, de opmerking was dat het niet duidelijk genoeg...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/pijltjes-collapse-accordion-twitter-bootstrap/">Pijltjes op de collapse / accordion van Twitter Bootstrap</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Recent kreeg ik feedback op een website die ik in het verleden gemaakt had waarbij de <a title="Ga naar de collapse documentatie" href="http://getbootstrap.com/2.3.2/javascript.html#collapse" target="_blank">collapse</a> van Twitter Bootstrap gebruikt wordt, de opmerking was dat het niet duidelijk genoeg was dat deze opengeklapt kunnen worden door aan te klikken. Zodoende hier pijltjes aan toegevoegd welke verdwijnen zodra er één geopend is. Hieronder zal ik uitleggen wat ik hiervoor aangepast heb.</p>
<p><a href="https://royduineveld.nl/wp-content/uploads/2013/09/collapse.png"><img class="aligncenter size-large wp-image-516" alt="Twitter Bootstrap Collapse" src="https://royduineveld.nl/wp-content/uploads/2013/09/collapse-1024x434.png" width="550" height="233" srcset="https://royduineveld.nl/wp-content/uploads/2013/09/collapse-1024x434.png 1024w, https://royduineveld.nl/wp-content/uploads/2013/09/collapse-300x127.png 300w, https://royduineveld.nl/wp-content/uploads/2013/09/collapse.png 1184w" sizes="(max-width: 550px) 100vw, 550px" /></a></p>
<h2>HTML aanpassen</h2>
<p>Voeg aan elke &#8220;accordion-heading&#8221; een afbeelding van een pijltje toe met een &#8220;pull-left&#8221;.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div class=&quot;accordion-heading&quot;&gt;
	&lt;h2&gt;&lt;i class=&quot;icon-chevron-down pull-left&quot;&gt;&lt;/i&gt; &lt;a class=&quot;accordion-toggle&quot; data-toggle=&quot;collapse&quot; data-parent=&quot;#wizard&quot; href=&quot;#brand&quot;&gt;Merk&lt;/a&gt;&lt;/h2&gt;
&lt;/div&gt;
</pre>
<h2>CSS toevoegen</h2>
<p>Zoals hierboven in de HTML te zien is heb ik heading 2 tags gebruikt, hier moest de margin voor het icoon dan ook op aangepast worden:</p>
<pre class="brush: css; title: ; notranslate">
.accordion .icon-chevron-down {
	margin: 9px 10px 0 15px;
}
</pre>
<h2>Javascript toevoegen</h2>
<p>Om het allemaal goed te laten functioneren heb ik een stukje Javascript toegevoegd welke inhaakt op de Javascript van de collapse. Zoals te zien wordt hier jQuery bij gebruikt.</p>
<pre class="brush: jscript; title: ; notranslate">
$('#wizard').on('show', function (e) {
	$('.accordion .icon-chevron-down').removeClass('hide');
	$(e.target).prev().children().children('.icon-chevron-down').addClass('hide');
});

$('#wizard').on('hide', function (e) {
	$('.accordion .icon-chevron-down').removeClass('hide');
});
</pre>
<blockquote><p>Mocht iemand zich geroepen voelen dit te melden bij Twitter Boostrap als toevoeging, ga je gang!</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/pijltjes-collapse-accordion-twitter-bootstrap/">Pijltjes op de collapse / accordion van Twitter Bootstrap</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/pijltjes-collapse-accordion-twitter-bootstrap/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Gemakkelijk miniaturen maken met GD Library</title>
		<link>https://royduineveld.nl/gemakkelijk-miniaturen-maken-met-gd-library/</link>
		<comments>https://royduineveld.nl/gemakkelijk-miniaturen-maken-met-gd-library/#respond</comments>
		<pubDate>Wed, 24 Jul 2013 19:11:49 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[GD Library]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=496</guid>
		<description><![CDATA[<p>Op het internet zijn tal van scripts te vinden om miniaturen te maken. Na een speurtocht uiteindelijk gekozen zelf een functie hiervoor te schrijven met de volgende functionaliteiten cq vereisten:...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/gemakkelijk-miniaturen-maken-met-gd-library/">Gemakkelijk miniaturen maken met GD Library</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Op het internet zijn tal van scripts te vinden om miniaturen te maken. Na een speurtocht uiteindelijk gekozen zelf een functie hiervoor te schrijven met de volgende functionaliteiten cq vereisten:</p>
<ul>
<li><span style="line-height: 13px;">Zowel de hoogte als de breedte in kunnen stellen</span></li>
<li>De miniatuur dient altijd gevuld te zijn, wanneer de verhouding dus niet gelijk is dient er wat afgesneden te worden</li>
<li>Gemakkelijk in gebruik, waaronder de afbeelding extensie niet op te hoeven geven</li>
<li>Eventueel meerdere formaten miniaturen te maken, dus een bestandsnaam met de grootte erin zodat deze niet overschreven worden</li>
</ul>
<p>Dit heeft het volgende resultaat opgeleverd:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * Create thumbnail (resize and/or crop image)
 * @param  string  $image  Source image
 * @param  integer $width  Thumbnail width
 * @param  integer $height Thumbnail height
 * @return string          The generated thumbnail
 */
function thumb($image,$width = 200,$height = 200)
{
	// Image set?
	if($image)
	{
		// Get the file information
		$fileinfo = pathinfo($image);

		// Set the thumbnail location
		$image_thumb = $fileinfo['dirname'] . '/thumb/' . $width . '-' . $fileinfo['basename'];

		// Thumbnail already exists?
		if(!file_exists($image_thumb))
		{
			// Get source as image
			$image = imagecreatefromstring(file_get_contents($image));

			// Set new size
			$thumb_width 		= $width;
			$thumb_height 		= $height;

			// Get image size
			$width 				= imagesx($image);
			$height 			= imagesy($image);

			// Calculate ratio
			$original_aspect 	= $width / $height;
			$thumb_aspect 		= $thumb_width / $thumb_height;

			// Image wider than new size?
			if ( $original_aspect &gt;= $thumb_aspect )
			{
				$new_height 	= $thumb_height;
				$new_width 		= $width / ($height / $thumb_height);
			}
			// New size wider than the image
			else
			{
				$new_width 		= $thumb_width;
				$new_height 	= $height / ($width / $thumb_width);
			}

			// Create new image
			$thumb = imagecreatetruecolor( $thumb_width, $thumb_height );

			// Resize and crop
			imagecopyresampled($thumb,
									$image,
									0 - ($new_width - $thumb_width) / 2, // Center the image horizontally
									0 - ($new_height - $thumb_height) / 2, // Center the image vertically
									0, 0,
									$new_width, $new_height,
									$width, $height);

			// Create and return image
			imagejpeg($thumb,$image_thumb);

			// Destroy
			imagedestroy($thumb);
		}

		// Return the thumbnail
		return $image_thumb;
	}
	else
	{
		// Set a placeholder
		return 'http://placehold.it/'.$width.'x'.$height;
	}
}
?&gt;
</pre>
<p>Tevens wordt er al gecontroleerd of de miniatuur al gemaakt is, hierdoor kan deze eventueel direct aangesproken worden door de functie te koppelen aan GET variabelen:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
if($_GET['thumb'])
{
	echo thumb($_GET['thumb'],200,200);
}
?&gt;
</pre>
<p>Wat vervolgens op de volgende manier gebruikt kan worden:</p>
<pre class="brush: xml; title: ; notranslate">&lt;img src=&quot;file.php?thumb=source-image.jpg&quot; alt=&quot;&quot;&gt;</pre>
<blockquote><p>Deze functie wordt onder andere gebruikt in een <a title="Ga naar mijn portfolio" href="https://royduineveld.nl/#/aalsmeerse-plantenhal" target="_blank">advertentie systeem</a> en op <a title="Ga naar Fastr" href="http://fastr.nl" target="_blank">Fastr</a>, een nieuw platform voor autoliefhebbers!</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/gemakkelijk-miniaturen-maken-met-gd-library/">Gemakkelijk miniaturen maken met GD Library</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/gemakkelijk-miniaturen-maken-met-gd-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Klanten in kaart brengen met Google Geolocation en Maps API</title>
		<link>https://royduineveld.nl/klanten-in-kaart-brengen-met-google-geolocation-en-maps-api/</link>
		<comments>https://royduineveld.nl/klanten-in-kaart-brengen-met-google-geolocation-en-maps-api/#respond</comments>
		<pubDate>Thu, 20 Jun 2013 18:11:41 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=485</guid>
		<description><![CDATA[<p>Wanneer je bijvoorbeeld een webshop hebt en je wilt weten waar je klanten wonen kan je natuurlijk door je klanten bestand bladeren en elke keer een streepje zetten bij een...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/klanten-in-kaart-brengen-met-google-geolocation-en-maps-api/">Klanten in kaart brengen met Google Geolocation en Maps API</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Wanneer je bijvoorbeeld een webshop hebt en je wilt weten waar je klanten wonen kan je natuurlijk door je klanten bestand bladeren en elke keer een streepje zetten bij een plaats. Leuker is om dit op de kaart te zien! Op die kaart kan uiteraard ingezoomd worden en staat er een icoontje op het adres van de klant met daarbij de naam.</p>
<p><a href="https://royduineveld.nl/wp-content/uploads/2013/06/google-maps-klanten-in-kaart-brengen.png"><img class="aligncenter size-medium wp-image-486" alt="Google Maps - Klanten in kaart brengen" src="https://royduineveld.nl/wp-content/uploads/2013/06/google-maps-klanten-in-kaart-brengen-300x291.png" width="300" height="291" srcset="https://royduineveld.nl/wp-content/uploads/2013/06/google-maps-klanten-in-kaart-brengen-300x291.png 300w, https://royduineveld.nl/wp-content/uploads/2013/06/google-maps-klanten-in-kaart-brengen.png 841w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<h2>Beginnen</h2>
<p>Om dit voor elkaar te krijgen kan je gebruik maken van Google API&#8217;s, waaronder Maps en Geolocation. Om hiervan gebruik te maken dien je eerst toegang te krijgen tot deze API&#8217;s. Ga hiervoor naar <a title="Ga naar Google API's Console" href="https://code.google.com/apis/console/">Google API&#8217;s Console</a>. Ga vervolgens naar &#8220;services&#8221; in het menu en zet de &#8220;Google Maps API v3&#8221; aan. Hierna ga je naar &#8220;API Access&#8221; in het menu en daar is de &#8220;API key&#8221; te vinden om toegang te krijgen. Eventueel kan je op &#8220;Edit allowed referers&#8221; klikken en hierna je domeinnaam invullen, op die manier is de betreffende API key enkel te gebruiken op die domeinnaam.</p>
<h2>Google Geolocation</h2>
<p>Voordat we alle klanten op de kaart kunnen zetten hebben we de coördinaten nodig van het adres. Hiervoor dienen we eerst verbinding te maken met de database waar de klanten in staan, vervolgens kunnen we één voor één de coördinaten opvragen. Maar zodra we deze hebben is het wel zo handig deze ook op te slaan! Maak twee nieuwe kolommen aan in het klanten tabel: &#8220;lat&#8221; en &#8220;lng&#8221;. Eventueel kan je als type een decimaal instellen. Ik heb voor simpelweg een &#8220;varchar&#8221; veld gekozen. Hierna kunnen we bijvoorbeeld het volgende stukje code gebruiken:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Hier uiteraard eerst een verbinding maken met de database

// Alle klanten ophalen welke nog géén coördinaten hebben
$query = mysqli_query('SELECT * FROM klanten WHERE lat=0 OR lng=0');

// Door alle opgehaalde klanten lopen
while($row = mysqli_fetch_assoc($query))
{
	// De URL maken met het adres, postcode en de woonplaats
	// van de klant om informatie over op te halen
	$url = 'http://maps.googleapis.com/maps/api/geocode/json?address='.urlencode($row['adres'].' '.$row['postcode'].' '.$row['plaats']).'&amp;sensor=false&amp;language=nl&amp;region=nl';

	// Het resultaat ophalen
	if($result = file_get_contents($url))
	{
		// Het resultaat is JSON, zodoende nog even decoderen
		$result = json_decode($result);

		// Kijken of het resultaat goed is
		if($result-&gt;status == 'OK')
		{
			// De locatie uit het resultaat ophalen
			$location = $result-&gt;results[0]-&gt;geometry-&gt;location;

			// De klant gegevens updaten met de coördinaten
			mysqli_query('UPDATE klanten SET lat=&quot;'.secure_in($location-&gt;lat).'&quot;, lng=&quot;'.secure_in($location-&gt;lng).'&quot; WHERE id='.$row['id']);
		}
	}
}
?&gt;
</pre>
<p>Door het draaien van dit stukje code worden dus de coördinaten aan de klant regels toegevoegd. In mijn geval moest ik dit script een aantal keren draaien voordat alle klanten de coördinaten hadden. Waarschijnlijk door limieten van deze API van Google. Eventueel kan je experimenteren met de <a title="Ga naar PHP's sleep functie" href="http://nl3.php.net/sleep" target="_blank">sleep functie</a>, wellicht dat er wat tijd tussen een verzoek moet zitten.</p>
<h2>Google Maps</h2>
<p>Nu de coördinaten bekend zijn kunnen deze geplaatst worden op een kaart! Hiervoor dient wél eerst de Maps API aangesproken te worden, zet hiervoor de volgende regel met je eigen API key in de &#8220;head&#8221;:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;https://maps.googleapis.com/maps/api/js?v=3&amp;key=HIER-JE-API-KEY&amp;sensor=false&amp;language=nl&amp;region=nl&quot;&gt;&lt;/script&gt;
</pre>
<p>En voeg vervolgens een div toe aan de &#8220;body&#8221; zoals ook gedaan wordt in de <a title="Ga naar de Google Maps API Documentatie" href="https://developers.google.com/maps/documentation/javascript/" target="_blank">Maps API documentatie</a>:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div id=&quot;map-canvas&quot;&gt;&lt;/div&gt;
</pre>
<p>Hierna openen we een script tag en kunnen we aan de gang! Eerst maar de Nederlandse kaart voor ons krijgen:</p>
<pre class="brush: jscript; title: ; notranslate">
// Nieuwe cq mooiere visuele weergave gebruiken
google.maps.visualRefresh = true;

// Functie die aangesproken wordt zodra de pagina geladen is
function initialize()
{
	// Kaart opties
	var mapOptions = {
		center: new google.maps.LatLng(52.23, 4.55), // Coördinaten van centraal Nederland
		zoom: 8, // Inzoomen zodat Nederland goed zichtbaar is
		mapTypeId: google.maps.MapTypeId.ROADMAP // De wegenkaart gebruiken
	};

	// Kaart laden in div met het ID map-canvas
	var map = new google.maps.Map(document.getElementById(&quot;map-canvas&quot;),mapOptions);
}

// Zodra de pagina is geladen de initialize functie aanspreken
google.maps.event.addDomListener(window, 'load', initialize);
</pre>
<p>Om de klanten op de kaart weer te geven dienen we deze eerst op te halen:</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;?php
// Alle klanten ophalen
$query = mysql_query('SELECT * FROM klanten');

// Door alle klanten lopen
while($row = mysql_fetch_assoc($query))
{
	// Een array opbouwen met de klant naam en coördinaten
	// (welke nog even van een komma naar een punt veranderd worden)
	$locations[] = '[&quot;'.$row['naam'].'&quot;,&quot;'.str_replace(',','.',$row['lat']).'&quot;,&quot;'.str_replace(',','.',$row['lng']).'&quot;]';
}
?&gt;

// De array met gegevens in Javascript
var locations = [
	&lt;?=implode(',',$locations); // De in PHP gemaakte array samenvoegen tot een regel gescheiden door komma's ?&gt;
];
</pre>
<p>Waarna we een nieuwe functie kunnen maken om de klanten op de kaart te zetten:</p>
<pre class="brush: jscript; title: ; notranslate">
function setMarkers(map,locations)
{
	// De afbeelding voor de klanten op de kaart
	var image = 'http://icons.iconarchive.com/icons/icons-land/vista-people/24/Office-Customer-Male-Light-icon.png';

	// Door alle klanten lopen
	for (var i = 0; i &lt; locations.length; i++)
	{
		// De coördinaten ophalen
		var loc = locations[i];
		var myLatLng = new google.maps.LatLng(loc[1], loc[2]);

		// De &quot;marker&quot; plaatsen
		var marker = new google.maps.Marker({
			position: myLatLng,
			map: map,
			icon: image,
			title: loc[0]
		});
	}
}
</pre>
<p>Het enige wat er nu nog moet gebeuren is deze functie aanspreken en het allemaal samenvoegen, met als resultaat:</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;?php
// Alle klanten ophalen
$query = mysql_query('SELECT * FROM klanten');

// Door alle klanten lopen
while($row = mysql_fetch_assoc($query))
{
	// Een array opbouwen met de klant naam en coördinaten
	// (welke nog even van een komma naar een punt veranderd worden)
	$locations[] = '[&quot;'.$row['naam'].'&quot;,&quot;'.str_replace(',','.',$row['lat']).'&quot;,&quot;'.str_replace(',','.',$row['lng']).'&quot;]';
}
?&gt;

// De array met gegevens in Javascript
var locations = [
	&lt;?=implode(',',$locations); // De in PHP gemaakte array samenvoegen tot een regel gescheiden door komma's ?&gt;
];

// Nieuwe cq mooiere visuele weergave gebruiken
google.maps.visualRefresh = true;

// Functie die aangesproken wordt zodra de pagina geladen is
function initialize()
{
	// Kaart opties
	var mapOptions = {
		center: new google.maps.LatLng(52.23, 4.55), // Coördinaten van centraal Nederland
		zoom: 8, // Inzoomen zodat Nederland goed zichtbaar is
		mapTypeId: google.maps.MapTypeId.ROADMAP // De wegenkaart gebruiken
	};

	// Kaart laden in div met het ID map-canvas
	var map = new google.maps.Map(document.getElementById(&quot;map-canvas&quot;),mapOptions);

	// De &quot;markers&quot; plaatsen
	setMarkers(map,locations);
}

// Functie die de &quot;markers&quot; plaatst op de kaart
function setMarkers(map,locations)
{
	// De afbeelding voor de klanten op de kaart
	var image = 'http://icons.iconarchive.com/icons/icons-land/vista-people/24/Office-Customer-Male-Light-icon.png';

	// Door alle klanten lopen
	for (var i = 0; i &lt; locations.length; i++)
	{
		// De coördinaten ophalen
		var loc = locations[i];
		var myLatLng = new google.maps.LatLng(loc[1], loc[2]);

		// De &quot;marker&quot; plaatsen
		var marker = new google.maps.Marker({
			position: myLatLng,
			map: map,
			icon: image,
			title: loc[0]
		});
	}
}

// Zodra de pagina is geladen de initialize functie aanspreken
google.maps.event.addDomListener(window, 'load', initialize);
</pre>
<blockquote><p>Dat is toch stukken leuker dan een lijst met plaatsnamen! Uiteraard is het aan alle kanten uit te breiden, voor inspiratie: bekijk de <a title="Ga naar de Google Maps API Documentatie" href="https://developers.google.com/maps/documentation/javascript/" target="_blank">Maps API documentatie</a> eens!</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/klanten-in-kaart-brengen-met-google-geolocation-en-maps-api/">Klanten in kaart brengen met Google Geolocation en Maps API</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/klanten-in-kaart-brengen-met-google-geolocation-en-maps-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter Bootstrap en CodeIgniter&#8217;s form validation</title>
		<link>https://royduineveld.nl/twitter-bootstrap-en-codeigniters-form-validation/</link>
		<comments>https://royduineveld.nl/twitter-bootstrap-en-codeigniters-form-validation/#respond</comments>
		<pubDate>Thu, 16 May 2013 19:00:39 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Twitter Bootstrap]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=454</guid>
		<description><![CDATA[<p>Ik ben een grootte fan van Twitter Bootstrap en gebruik dit dan ook graag, het ziet er goed uit en ermee werken is kinderlijk eenvoudig. Voor het functionele gedeelte maak...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/twitter-bootstrap-en-codeigniters-form-validation/">Twitter Bootstrap en CodeIgniter&#8217;s form validation</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Ik ben een grootte fan van Twitter Bootstrap en gebruik dit dan ook graag, het ziet er goed uit en ermee werken is kinderlijk eenvoudig. Voor het functionele gedeelte maak ik graag gebruik van het CodeIgniter framework waarin allerlei handige functionaliteiten, waaronder <a title="Ga naar de Form Validation handleiding voor CodeIgniter" href="http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html" target="_blank">Form Validation</a>. Deze PHP class of &#8220;library&#8221; genoemd in CodeIgniter maakt het valideren van een formulier stukken makkelijker. Als voorbeeld:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// De controller welke de controller van CodeIgniter uitbreid
class Formulier extends CI_Controller
{
	// De index functie welke als eerst aangesproken wordt
	// wanneer de controller geladen is
	public function index()
	{
		// De library laden zodat deze gebruikt kan worden
		// Eventueel ook automatisch te laden via autoload.php
		$this-&gt;load-&gt;library('form_validation');

		// De p-tags verwijderen rondom validatie foutmeldingen
		// Normaal is dit: &lt;p&gt;Foutmelding...&lt;/p&gt;
		$this-&gt;form_validation-&gt;set_error_delimiters('', '');

		// Regels instellen voor ingevulde velden
		// De eerste waarde is de &quot;name&quot; van de input
		// De tweede waarde is de volledige naam van het veld
		// De derde waarde zijn de validatie regels:
		// - required = Verplicht in te vullen
		// - max_length[255] = Maximaal 255 karakters lang
		// - valid_email = Een geldig email adres
		// - trim = De PHP trim functie
		$this-&gt;form_validation-&gt;set_rules('name', 'Naam', 'required|max_length[255]|trim');
		$this-&gt;form_validation-&gt;set_rules('email', 'Email', 'required|valid_email|max_length[255]|trim');

		// Is het formulier verstuurd en is de validatie geslaagd?
		if( $this-&gt;form_validation-&gt;run()  )
		{
			// Ja!
			// Doe iets met de waardes,
			// opslaan in een database bijvoorbeeld
		}
		else
		{
			// Nee!
			// Het formulier weergeven
			$this-&gt;load-&gt;view('header');
			$this-&gt;load-&gt;view('formulier');
			$this-&gt;load-&gt;view('footer');
		}
	}
}
</pre>
<p>De &#8220;header&#8221; en &#8220;footer&#8221; view laten we even achterwege, door naar het formulier! Om de eventuele foutmeldingen weer te geven is de <a title="Ga naar de Helper Reference van de Form Validation library" href="http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#helperreference" target="_blank">validation_errors</a> functie, maar deze set alle foutmeldingen onder elkaar. Bij een mooi formulier ziet het er stukken beter uit als achter het veld een eventuele foutmelding komt te staan. Zie ook <a title="Ga naar de voorbeelden van formulier met Twitter Bootstrap" href="http://twitter.github.io/bootstrap/base-css.html#forms" target="_blank">de voorbeelden</a> van Twitter Bootstrap (vrij onderaan, je kan beter eerst naar buttons gaan en dan naar boven scrollen). Om dit voor elkaar te krijgen is er de <a title="Ga naar de Helper Reference van de Form Validation library" href="http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#helperreference" target="_blank">form_error</a> functie. Deze in combinatie met de <a title="Ga naar de Helper Reference van de Form Validation library" href="http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#helperreference" target="_blank">set_value</a> functie maakt het af. Deze laatste zorgt er namelijk voor dat de ingevulde waardes blijven, wanneer de validatie mislukt is, na het versturen van het formulier. Dit bij elkaar gestopt resulteert in het volgende:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;h1&gt;Gebruiker &lt;?=(isset($id) ? 'bewerken' : 'toevoegen');?&gt;&lt;/h1&gt;
&lt;hr&gt;
&lt;?=form_open('',array('class' =&gt; 'form-horizontal'));?&gt;
	&lt;div class=&quot;control-group&lt;?=form_error('name') ? ' error' : '';?&gt;&quot;&gt;
		&lt;label class=&quot;control-label&quot; for=&quot;name&quot;&gt;Naam&lt;/label&gt;
		&lt;div class=&quot;controls&quot;&gt;
			&lt;input type=&quot;text&quot; id=&quot;name&quot; name=&quot;name&quot; placeholder=&quot;Naam&quot; value=&quot;&lt;?=set_value('name',(isset($name) ? $name : '')); ?&gt;&quot;&gt;
			&lt;span class=&quot;help-inline&quot;&gt;&lt;?=form_error('name'); ?&gt;&lt;/span&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;div class=&quot;control-group&lt;?=form_error('email') ? ' error' : '';?&gt;&quot;&gt;
		&lt;label class=&quot;control-label&quot; for=&quot;email&quot;&gt;Email&lt;/label&gt;
		&lt;div class=&quot;controls&quot;&gt;
			&lt;input type=&quot;email&quot; id=&quot;email&quot; name=&quot;email&quot; placeholder=&quot;Email adres&quot; value=&quot;&lt;?=set_value('email',(isset($email) ? $email : '')); ?&gt;&quot;&gt;
			&lt;span class=&quot;help-inline&quot;&gt;&lt;?=form_error('email'); ?&gt;&lt;/span&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;div class=&quot;control-group&quot;&gt;
		&lt;div class=&quot;controls&quot;&gt;
			&lt;button type=&quot;submit&quot; class=&quot;btn btn-success&quot;&gt;&lt;i class=&quot;icon-ok icon-white&quot;&gt;&lt;/i&gt; Opslaan&lt;/button&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/form&gt;
</pre>
<p>Eén ding heb ik nog niet uitgelegd! Programmeren volgens <a title="Ga naar Wikipedia over DRY" href="http://en.wikipedia.org/wiki/Don't_repeat_yourself" target="_blank">DRY</a> houd dus ook géén dubbele formulieren in. Vandaar de <a title="Ga naar de isset functie van PHP" href="http://php.net/isset" target="_blank">isset</a> functies. Het formulier om iets toe te voegen en iets te bewerken kan dus samengevoegd worden. Wanneer dit formulier vanuit de controller geladen wordt zijn er geen waardes ingevuld. Willen we deze wel ingevuld hebben; dienen we deze enkel door te geven. De aangevulde en iets bewerkte controller:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// De controller welke de controller van CodeIgniter uitbreid
class Formulier extends CI_Controller
{
	// De &quot;constructor&quot;, deze wordt altijd voor de losse functies uitgevoerd
	public function __construct()
	{
		// Zorgen dat de &quot;constructor&quot; van de CI_Controller eerst uitgevoerd wordt
		parent::__construct();

		// De library laden zodat deze gebruikt kan worden
		// Eventueel ook automatisch te laden via autoload.php
		$this-&gt;load-&gt;library('form_validation');

		// De p-tags verwijderen rondom validatie foutmeldingen
		// Normaal is dit: &lt;p&gt;Foutmelding...&lt;/p&gt;
		$this-&gt;form_validation-&gt;set_error_delimiters('', '');

		// Regels instellen voor ingevulde velden
		// De eerste waarde is de &quot;name&quot; van de input
		// De tweede waarde is de volledige naam van het veld
		// De derde waarde zijn de validatie regels:
		// - required = Verplicht in te vullen
		// - max_length[255] = Maximaal 255 karakters lang
		// - valid_email = Een geldig email adres
		// - trim = De PHP trim functie
		$this-&gt;form_validation-&gt;set_rules('name', 'Naam', 'required|max_length[255]|trim');
		$this-&gt;form_validation-&gt;set_rules('email', 'Email', 'required|valid_email|max_length[255]|trim');
	}

	// De index functie welke als eerst aangesproken wordt
	// wanneer de controller geladen is, dus:
	// http://website.nl/formulier
	public function index()
	{
		// Is het formulier verstuurd en is de validatie geslaagd?
		if( $this-&gt;form_validation-&gt;run()  )
		{
			// Ja! Opslaan in de database
			$this-&gt;db-&gt;insert('gebruikers',$this-&gt;input-&gt;post());

			// Doorsturen naar de begin pagina
			redirect( site_url() );
		}
		else
		{
			// Nee! Het formulier weergeven
			$this-&gt;load-&gt;view('header');
			$this-&gt;load-&gt;view('formulier');
			$this-&gt;load-&gt;view('footer');
		}
	}

	// De bijwerken functie
	// http://website.nl/formulier/edit/1
	public function edit($id = 0)
	{
		// Gegevens uit de database halen
		$data = $this-&gt;db-&gt;get_where('gebruikers',array('id' =&gt; $id))-&gt;row();

		// Niets gevonden in de database?
		if(empty($data))
		{
			// Foutmelding weergeven
			show_404();
		}

		// Is het formulier verstuurd en is de validatie geslaagd?
		if( $this-&gt;form_validation-&gt;run()  )
		{
			// Ja! Bewerken in de database
			$this-&gt;db-&gt;where('id',$id);
			$this-&gt;db-&gt;update('gebruikers',$this-&gt;input-&gt;post());

			// Doorsturen naar de begin pagina
			redirect( site_url() );
		}
		else
		{
			// Nee! Het formulier weergeven
			// Deze keer de waardes uit de database meegeven
			$this-&gt;load-&gt;view('header');
			$this-&gt;load-&gt;view('formulier',$data);
			$this-&gt;load-&gt;view('footer');
		}
	}
}
</pre>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/twitter-bootstrap-en-codeigniters-form-validation/">Twitter Bootstrap en CodeIgniter&#8217;s form validation</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/twitter-bootstrap-en-codeigniters-form-validation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Waardes behouden na verzenden van dynamisch formulier</title>
		<link>https://royduineveld.nl/waardes-behouden-na-verzenden-van-dynamisch-formulier/</link>
		<comments>https://royduineveld.nl/waardes-behouden-na-verzenden-van-dynamisch-formulier/#respond</comments>
		<pubDate>Mon, 13 May 2013 18:19:53 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Local Storage]]></category>
		<category><![CDATA[Session Storage]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=449</guid>
		<description><![CDATA[<p>Na het verzenden én vervolgens op de &#8220;vorige knop&#8221; geklikt te hebben zijn alle ingevulde waardes van een dynamisch formulier verdwenen. Ofwel, een formulier waarbij met Javascript elementen toegevoegd worden....</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/waardes-behouden-na-verzenden-van-dynamisch-formulier/">Waardes behouden na verzenden van dynamisch formulier</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Na het verzenden én vervolgens op de &#8220;vorige knop&#8221; geklikt te hebben zijn alle ingevulde waardes van een dynamisch formulier verdwenen. Ofwel, een formulier waarbij met Javascript elementen toegevoegd worden. Om dit op te lossen zijn er meerdere mogelijkheden:</p>
<ul>
<li><span style="line-height: 13px;">Formulier middels Ajax verzenden, zodat de pagina niet opnieuw geladen hoeft te worden</span></li>
<li>De waardes middels Ajax opslaan en opnieuw inladen</li>
<li>De gegevens lokaal opslaan, dit voor het verzenden</li>
</ul>
<p>Ik heb recent gekozen voor de laatste optie. Voordat ik de oplossing hiervoor laat zien, eerst wat materiaal om mee te werken. Laten we een eenvoudig formulier nemen:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;form action=&quot;&quot; method=&quot;POST&quot;&gt;
	&lt;table&gt;
		&lt;tr id=&quot;eerste-regel&quot;&gt;
			&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;name[]&quot; placeholder=&quot;Naam...&quot;&gt;&lt;/td&gt;
			&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;number[]&quot; placeholder=&quot;Nummer...&quot;&gt;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;
	&lt;a href=&quot;#&quot; id=&quot;regel-toevoegen&quot;&gt;Regel toevoegen&lt;/a&gt; &lt;input type=&quot;submit&quot; value=&quot;Verzenden!&quot;&gt;
&lt;/form&gt;
</pre>
<p>Het volgende stukje Javascript in samenwerking met jQuery zorgt ervoor dat wanneer er op &#8220;Regel toevoegen&#8221; geklikt wordt er een nieuwe regel bij komt:</p>
<pre class="brush: jscript; title: ; notranslate">
// Regel toevoegen geklikt?
$('#regel-toevoegen').click(function()
{
	// Eerste regel ophalen
	var regel = $('#eerste-regel').clone();

	// ID verwijderen
	regel.removeAttr('id');

	// Ingevulde waardes verwijderen
	regel.find('input').val('');

	// Nieuwe regel toevoegen en het ID en de ingevulde waardes verwijderen
	$('table').append( regel );

	// False terug sturen zodat de pagina niet verspringt
	return false;
});
</pre>
<p>Hier kunnen we op verder bouwen! Want wanneer je meerdere regels toevoegt, deze invult en na het klikken op &#8220;Verzenden!&#8221; terug gaat; is al je kostbare werk verloren gegaan. Om de gegevens voordat deze verzonden worden op te slaan, dienen we dit af te vangen waarna we deze gestructureerd op kunnen slaan. Zie het volgende stukje code:</p>
<pre class="brush: jscript; title: ; notranslate">
// Form versturen?
$('form').submit(function()
{
	// Object met array's maken
	var array           = {};
	array['name']       = [];
	array['number']		= [];
	array['counter']    = 0;

	// Door alle tabel regels loopen
	$('tr').each(function()
	{
		array['name'].push( $(this).find('input[name=&quot;name[]&quot;]').val() );
		array['number'].push( $(this).find('input[name=&quot;number[]&quot;]').val() );
		array['counter']++;
	});

	// Opslaan in session storage
	sessionStorage.setItem('input', JSON.stringify(array));
});
</pre>
<p>Eerst vangen we de &#8220;submit&#8221; af, hierna bouwen we een object op met array&#8217;s gevolgd door alle ingevulde waardes hierin te zetten. Tevens draait er een tellertje mee om het aantal velden te bepalen. Als laatste worden de gegevens opgeslagen in &#8220;Session Storage&#8221;. In cookies kan je weinig kwijt en &#8220;Local Storage&#8221; bewaard de gegevens ook nadat het browser venster gesloten is, vandaar deze keuze. Let daarbij wel op dat je geen object of array in session of local storage kan opslaan. Hiervoor dient deze eerst omgezet te worden naar een &#8220;string&#8221;, vandaar de &#8220;stringify&#8221; functie. Hartstikke mooi dat het opgeslagen is, maar het moet er ook weer uit natuurlijk! Zie:</p>
<pre class="brush: jscript; title: ; notranslate">
// Iets in session storage aanwezig?
if(sessionStorage.getItem('input'))
{
	// Gegevens ophalen
	var array = JSON.parse( sessionStorage.getItem('input') );

	// Nieuwe regels toevoegen, minus de al aanwezige
	for (var n = 0; n &lt; (array['counter'] - 1); ++ n)
	{
		$('#regel-toevoegen').click();
	}

	// Door alle tabel regels loopen
	$('tr').each(function(index,value)
	{
		// Waarde plaatsen
		$(this).find('input[name=&quot;name[]&quot;]').val( array['name'][index] );
		$(this).find('input[name=&quot;number[]&quot;]').val( array['number'][index] );
	});

	// Waardes weer verwijderen
	sessionStorage.removeItem('input');
}
</pre>
<p>Eerst maar kijken of er iets aanwezig is, wanneer dat het geval is de gegevens ophalen en van de &#8220;string&#8221; weer een object met array&#8217;s maken. De teller laten lopen en elke keer even op de &#8220;Regel toevoegen&#8221; knop klikken. Vervolgens het zelfde stukje als bij het opslaan, enkel plaatsen we nu de gegevens terug in plaats van dat we deze uitlezen. Als toetje de gegevens nog even verwijderen en klaar!</p>
<p><a href="https://royduineveld.nl/demos/waardes-behouden-na-verzenden/" class="demo-button" target="_blank">Klik hier voor een online demo</a></p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/waardes-behouden-na-verzenden-van-dynamisch-formulier/">Waardes behouden na verzenden van dynamisch formulier</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/waardes-behouden-na-verzenden-van-dynamisch-formulier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>App maken met Phonegap en Phonegap Build</title>
		<link>https://royduineveld.nl/app-maken-met-phonegap-en-phonegap-build/</link>
		<comments>https://royduineveld.nl/app-maken-met-phonegap-en-phonegap-build/#comments</comments>
		<pubDate>Tue, 30 Apr 2013 13:26:47 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[Cordova]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Phonegap]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=413</guid>
		<description><![CDATA[<p>Phonegap maakt het mogelijk om super eenvoudig een app te maken met HTML, CSS en Javascript. Dit voor verschillende mobiele platformen als onder andere Android, iOS, Blackberry OS en Windows...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/app-maken-met-phonegap-en-phonegap-build/">App maken met Phonegap en Phonegap Build</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Phonegap maakt het mogelijk om super eenvoudig een app te maken met HTML, CSS en Javascript. Dit voor verschillende mobiele platformen als onder andere Android, iOS, Blackberry OS en Windows Phone. Als je dit voor het eerste hoort zal je denken dat het géén native app is en dus géén functionaliteiten (camera, bestandssysteem, notificaties, enz) kan gebruiken van de telefoon (ik houd het in dit artikel op telefoon, maar hiermee bedoel ik natuurlijk ook tablet). Dit kan juist wél! Om eerst de verschillen even uit te leggen tussen navtive-, web-, en hybride apps:</p>
<h2>Soorten apps</h2>
<h3>Native app</h3>
<blockquote><p>Een platform afhankelijk applicatie. Niet bij elk platform kan je in eenzelfde programmeer taal ontwikkelen en dus zal je voor elk platform een totaal nieuwe app moeten maken. Daarin tegen kan je met een native app wél alle mogelijkheden van een telefoon benutten en is er géén internet noodzakelijk om te functioneren.</p></blockquote>
<h3>Web app</h3>
<blockquote><p>Simpel gezegd; een website in een app jasje, alsof het een echte app is. Een mobiele website wordt ook wel eens een web app genoemd. Nadeel is dat géén functionaliteiten van de telefoon aangesproken kunnen worden en dat wanneer er geen internet is deze niet functioneert. (in een ander artikel heb een methode beschreven om een website wél offline beschikbaar te maken: <a title="Website offline beschikbaar maken met een submit fallback" href="https://royduineveld.nl/html/47/website-offline-beschikbaar-maken-met-een-submit-fallback/">Website offline beschikbaar maken met een submit fallback</a>)</p></blockquote>
<h3>Hybride app</h3>
<blockquote><p>Een combinatie van een native app en een web app waarbij dus vrijwel alles mogelijk is. Nadeel is dat er ook twee omgevingen bijgehouden dienen te worden, zowel het native als het web gedeelte.</p></blockquote>
<h2>Wat is Phonegap?</h2>
<p>Phonegap is een distributie van <a title="Ga naar Apache Cordova" href="http://cordova.apache.org/" target="_blank">Apache Cordova</a>. Phonegap maakt het ten opzichte van Cordova enkel wat makkelijker met <a title="Ga naar Phonegap Build" href="https://build.phonegap.com/" target="_blank">Phonegap Build</a> en &#8220;<a title="Ga naar de documentantie over Phonegap Hydration" href="https://build.phonegap.com/docs/hydration" target="_blank">hydration</a>&#8220;. Met Phonegap een app maken behoort tot een hybride app. Phonegap ofwel Cordova is dan het native gedeelte. Dit zorgt ervoor dat via Javascript functionaliteiten van de telefoon aangesproken kunnen worden. Benieuwd welke apps met Phonegap gemaakt zijn? Kijk eens <a title="Ga naar een overzicht van met Phonegap gemaakte apps" href="http://phonegap.com/app/" target="_blank">hier</a>.</p>
<h3>Wat is Phonegap Build?</h3>
<p>Dit maakt het mogelijk om je HTML, CSS en Javascript in te voeren en vervolgens zorgt de Build service ervoor dat er apps uit komen. In het geval van Android dus een apk bestand. Ter verduidelijking:</p>
<p><a href="https://royduineveld.nl/wp-content/uploads/2013/04/build-diagram1.png"><img class="aligncenter size-large wp-image-416" alt="Phonegap Build" src="https://royduineveld.nl/wp-content/uploads/2013/04/build-diagram1-1024x353.png" width="550" height="189" srcset="https://royduineveld.nl/wp-content/uploads/2013/04/build-diagram1-1024x353.png 1024w, https://royduineveld.nl/wp-content/uploads/2013/04/build-diagram1-300x103.png 300w, https://royduineveld.nl/wp-content/uploads/2013/04/build-diagram1.png 1450w" sizes="(max-width: 550px) 100vw, 550px" /></a></p>
<h3>Wat is Hydration?</h3>
<p>Tijdens het testen van een app, in het geval van Android; dien je elke keer een apk op je telefoon te zetten en vervolgens de al aanwezige cq oude app te updaten. Hydration maakt het mogelijk om updates te &#8220;pushen&#8221;. Door de app opnieuw te starten wordt automatisch de nieuwe versie gedownload en gebruikt. Eventueel kan je ook met <a title="Ga naar de Ripple Phonegap Emulator" href="http://emulate.phonegap.com/" target="_blank">Ripple</a> werken, dit is een emulator. Om de emulator te gebruiken dient wel je app &#8220;te draaien&#8221; ofwel lokaal middels bijvoorbeeld <a title="Ga naar Xampp" href="http://www.apachefriends.org/en/xampp.html" target="_blank">XAMPP</a> of simpelweg bij je hosting partij. Van Ripple is ook een <a title="Ga naar Ripple Emulator Google Chrome extensie" href="https://chrome.google.com/webstore/detail/ripple-emulator-beta/geelfhphabnejjhdalkjhgipohgpdnoc" target="_blank">extensie</a> beschikbaar voor Google Chrome.</p>
<h2>Eindelijk, beginnen!</h2>
<p>Eerst maar een <a title="Ga naar Phonegap Build om een account aan te maken" href="https://build.phonegap.com/plans/free" target="_blank">account aanmaken</a> bij Phonegap Build. Hierna <a title="Download Phonegap start" href="https://github.com/phonegap/phonegap-start/archive/master.zip" target="_blank">downloaden</a> we <a title="Ga naar de Phonegap start github pagina" href="https://github.com/phonegap/phonegap-start" target="_blank">phonegap-start</a>. Hierin zitten alle basis elementen voor een app. Dit is een soort van boilerplate als ook voor html beschikbaar is: <a title="Ga naar HTML 5 Boilerplate" href="http://html5boilerplate.com/" target="_blank">HTML5Boilerplate</a>. Na het downloaden en uitpakken van phonegap-start; pakken we alles gelijk weer in, maar enkel de bestanden in de www map. Terug naar de browser en de Phonegap Build website waar we een nieuwe app gaan maken. Hierbij krijg je de keuze om een open-source app te maken waarbij je de code op Github beschikbaar stelt. De andere optie is een &#8220;private&#8221; app, eventueel ook via Github te regelen. Wij kiezen voor zelf een zip bestand uploaden waarbij we het zojuist gemaakte zip bestand kiezen.</p>
<p><a href="https://royduineveld.nl/wp-content/uploads/2013/04/phonegap-new-app.png"><img class="aligncenter size-large wp-image-418" alt="Phonegap nieuwe app maken" src="https://royduineveld.nl/wp-content/uploads/2013/04/phonegap-new-app-1024x659.png" width="550" height="353" srcset="https://royduineveld.nl/wp-content/uploads/2013/04/phonegap-new-app-1024x659.png 1024w, https://royduineveld.nl/wp-content/uploads/2013/04/phonegap-new-app-300x193.png 300w, https://royduineveld.nl/wp-content/uploads/2013/04/phonegap-new-app.png 1204w" sizes="(max-width: 550px) 100vw, 550px" /></a></p>
<p>Na de upload kunnen we de eventueel debugging en hydration aanzetten. Door vervolgens op &#8220;ready to build&#8221; te klikken worden de apps voor de beschikbare platformen gemaakt! Zodra gereed krijgen de iconen van de platformen kleur en kunnen deze aangeklikt worden om de app te downloaden. In het geval van Android dus het apk bestand. Dit bestand kan je vervolgens op je telefoon zetten, makkelijker is om het QR code te scannen.</p>
<h3>App aanpassen</h3>
<p>Hartstikke leuk zo&#8217;n app die enkel &#8220;Device is Ready&#8221; zegt maar het kan niks! Om de app aan te passen beginnen we bij het config.xml bestand. Hierin staat alle informatie over de app als de naam, omschrijving, permissies en iconen. Pas dit bestand naar je wensen aan en mochten er onduidelijkheden zijn, lees de <a title="Ga naar de config.xml documentatie" href="https://build.phonegap.com/docs/config-xml" target="_blank">documentatie</a> hierover. Voordat je alle gewenste formaten iconen gaat maken voor je app, denk even na voor welke platformen je de app echt gaat gebruiken. Niet alles in het config.xml bestand is namelijk verplicht! Hierna kan je met index.html aan de gang gaan. Gebruik bijvoorbeeld <a title="Ga naar jQuery Mobile" href="http://jquerymobile.com/" target="_blank">jQuery Mobile</a> om je app er grafisch goed uit te laten zien. Eventueel kan je meerdere html bestanden maken mocht je app uit meerdere &#8220;pagina&#8217;s&#8221; bestaan. Gebruik alles wat je in huis hebt om een mooie app te maken middels HTML, CSS en Javascript. Om te testen kan je zoals eerder aangegeven Ripple gebruiken of je zipt alles in de www map nogmaals en upload dit via de &#8220;Update code&#8221; knop op de website van Phonegap Build.</p>
<h3>Telefoon functies aanspreken</h3>
<p>Ga ik nog een keer; hartstikke mooi die app maar ik wil de functies van een telefoon gebruiken! Alle informatie hierover kan je in de <a title="Ga naar de documentatie van Phonegap" href="http://docs.phonegap.com/" target="_blank">documentatie</a> van Phonegap vinden. Ik zal in dit artikel de camera aanspreken en een foto maken. Wat de permissies betreft in de documentatie, dit kan je overslaan gezien Phonegap Build dit regelt in de config.xml. Om de camera permissie te krijgen dien je de volgende regel toe te voegen in config.xml:</p>
<pre class="brush: xml; title: ; notranslate">&lt;feature name=&quot;http://api.phonegap.com/1.0/camera&quot;/&gt;</pre>
<p>Zie hiervoor &#8220;PhoneGap API Features&#8221; in de <a title="Ga naar de Phonegap Build config.xml documentatie" href="https://build.phonegap.com/docs/config-xml" target="_blank">config.xml documentatie</a>.</p>
<p>Om een foto te maken hebben we een knop nodig, na index.html wat opgeschoond te hebben zou dit er ongeveer zo uit moeten zien:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
	&lt;head&gt;
		&lt;meta charset=&quot;utf-8&quot; /&gt;
		&lt;meta name=&quot;format-detection&quot; content=&quot;telephone=no&quot; /&gt;
		&lt;meta name=&quot;viewport&quot; content=&quot;user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi&quot; /&gt;
		&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;css/index.css&quot; /&gt;
		&lt;title&gt;Foto maken&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div class=&quot;app&quot;&gt;
			&lt;h1&gt;Foto!&lt;/h1&gt;
			&lt;button id=&quot;maak-foto&quot;&gt;Maken&lt;/button&gt;
		&lt;/div&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;phonegap.js&quot;&gt;&lt;/script&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;js/index.js&quot;&gt;&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Zoals je ziet worden hier twee javascript bestanden aangesproken. Wat je wellicht is opgevallen is dat phonegap.js niet aanwezig is in de map! Dit klopt, deze wordt middels de Phonegap Build toegevoegd. De vermelding dan ook gewoon laten staan om de mogelijkheden van de telefoon aan te spreken. Door naar het index.js bestand! Middels Javascript kan je uiteindelijk de functies aanspreken, bij websites maak ik graag gebruik van jQuery, laten we dat dan hier ook doen! Ga naar de website van jQuery, download de laatste versie en sla deze op in de &#8220;js&#8221; map. Vervolgens moet hier nog wel even naar gelinkt worden vanuit het index.html bestand. Voeg na het phonegap.js regel de volgende regel toe:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.js&quot;&gt;&lt;/script&gt;
</pre>
<p>Vanuit een CDN laden kan natuurlijk ook, maar om de app ook zonder internet te laten functioneren is dit nu geen goed idee. Na ook het index.js bestand wat opgeschoond te hebben en de camera documentatie doorgespit te hebben, het volgende resultaat:</p>
<pre class="brush: jscript; title: ; notranslate">
// Anonieme functie openen
(function()
{
	// Wachten tot het apparaat klaar is
	document.addEventListener('deviceready', onDeviceReady, false);

	// Het apparaat is klaar
	function onDeviceReady()
	{
		// Telefoon functies kunnen pas aangesproken worden
		// wanneer het apparaat klaar is. Ofwel wanneer deze
		// functie aangesproken wordt kunnen deze pas gebruikt
		// worden. Aangezien de gebruiker hoogst waarschijnlijk
		// niet eerder op de foto maken knop klikt dan dat het
		// apparaat klaar is, maak ik hier nu geen gebruik van.
	}

	// Foto nemen is gelukt
	function cameraSuccess(imageData)
	{
		// Na de foto maken knop de afbeelding weergeven
		$('#maak-foto').after('&lt;img src=&quot;' + &quot;data:image/jpeg;base64,&quot; + imageData + '&quot;&gt;');
	}

	// Foto nemen is mislukt
	function cameraError(message)
	{
		// Foutmelding weergeven
		alert('Er ging iets fout! ' + message);
	}

	// Op de foto maken knop geklikt
	$('#maak-foto').click(function()
	{
		// Eventueel eerder gemaakte foto verwijderen
		$('img').remove();

		// Foto maken
		navigator.camera.getPicture( cameraSuccess, cameraError, {
			quality: 50, // Foto kwaliteit
			destinationType: Camera.DestinationType.DATA_URL // Base64 gecodeerde afbeelding als resultaat
		});
	});

// Functie direct uitvoeren
})();
</pre>
<p>Dit kan natuurlijk aan alle kanten uitgebreid worden. Van netjes vormgeven tot de afbeelding middels Ajax naar een server versturen.</p>
<blockquote><p>Schoot me net te binnen en klonk wel leuk: App? Use Phonegap!</p></blockquote>
<h2>Updates</h2>
<p>11-05-2013 &#8211; Inmiddels is er een cursus beschikbaar bij Tutsplus, erg leerzaam: <a href="https://tutsplus.com/course/phone-gap-essentials/">https://tutsplus.com/course/phone-gap-essentials/</a></p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/app-maken-met-phonegap-en-phonegap-build/">App maken met Phonegap en Phonegap Build</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/app-maken-met-phonegap-en-phonegap-build/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Responsive slider in WordPress met backend</title>
		<link>https://royduineveld.nl/responsive-slider-in-wordpress-met-backend/</link>
		<comments>https://royduineveld.nl/responsive-slider-in-wordpress-met-backend/#respond</comments>
		<pubDate>Fri, 19 Apr 2013 12:17:28 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=390</guid>
		<description><![CDATA[<p>Voor WordPress zijn er gigantisch veel sliders te vinden als plugin. Ik was op zoek naar een responsive slider voor in de header met een gemakkelijke backend om foto&#8217;s toe...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/responsive-slider-in-wordpress-met-backend/">Responsive slider in WordPress met backend</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Voor WordPress zijn er <a title="Wordpress plugin pagina met sliders" href="http://wordpress.org/extend/plugins/search.php?q=slider" target="_blank">gigantisch veel sliders</a> te vinden als plugin. Ik was op zoek naar een responsive slider voor in de header met een gemakkelijke backend om foto&#8217;s toe te voegen. Na een lange speurtocht besloten om dit zelf te regelen. Uiteindelijk gekozen voor een populaire slider: <a title="Website van Nivo Slider" href="http://dev7studios.com/nivo-slider/" target="_blank">Nivo Slider</a>. De Javascript en CSS bestanden toegevoegd in &#8220;lib/scripts.php&#8221; en de nodige HTML in de header. In mijn geval in &#8220;header-top-navbar.php&#8221; gezien ik gebruik maak van het <a title="Website van het Roots starter theme" href="http://www.rootstheme.com/" target="_blank">Roots starter theme</a>. Top, maar nu de backend? Er zit al een mediabibliotheek in de WordPress backend, waarom hier niet gebruik van maken! Afbeeldingen kunnen geupload, geroteerd, gespiegeld, geschaald en bijgesneden worden. Helemaal compleet dus! Maar niet alle afbeeldingen in de mediabibliotheek moeten in de slider komen. Zodoende gekozen voor een &#8220;filter&#8221; op de &#8220;<a title="Informatie over alt-text op Wikipedia" href="http://en.wikipedia.org/wiki/Alt_attribute" target="_blank">alt-text</a>&#8221; ofwel alternatieve tekst mocht de afbeelding niet weergegeven kunnen worden. Wanneer die gelijk is aan &#8220;slider&#8221; moet deze in de slider komen. Na wat zoek werk in de database tot de volgende MySQL query gekomen:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT
	second.meta_value
FROM
	wp_postmeta as first
JOIN
	wp_postmeta as second
ON
	first.post_id = second.post_id AND second.meta_key = &quot;_wp_attached_file&quot;
WHERE
	first.meta_value=&quot;slider&quot;
</pre>
<p>Hierbij wordt gezocht naar &#8220;meta_value&#8221;: &#8220;slider&#8221;. Aan de hand van het &#8220;post_id&#8221; wordt gezocht naar de afbeelding welke als &#8220;meta_key&#8221;: &#8220;_wp_attached_file&#8221; heeft. Dit verwerkt naar &#8220;WordPress taal&#8221; met daarbij de <a title="Multidimensionale array naar enkele array" href="https://royduineveld.nl/php/327/multidimensionale-array-naar-enkele-array/">multidimensionale array geconverteerd naar een enkele array</a> met als resultaat:</p>
<pre class="brush: php; title: ; notranslate">
$results = $wpdb-&gt;get_results('
	SELECT
		second.meta_value
	FROM
		'.$wpdb-&gt;postmeta.' as first
	JOIN
		'.$wpdb-&gt;postmeta.' as second
	ON
		first.post_id = second.post_id AND second.meta_key = &quot;_wp_attached_file&quot;
	WHERE
		first.meta_value=&quot;slider&quot;
	',ARRAY_N);
$results = array_map(function($array){return $array[0];},$results);
</pre>
<p>Nu het resultaat nog in de slider zetten:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div id=&quot;slider&quot; class=&quot;nivoSlider&quot;&gt;
	&lt;? foreach($results as $result): ?&gt;
	&lt;img src=&quot;assets/&lt;?=$result;?&gt;&quot; alt=&quot;&quot;&gt;
	&lt;? endforeach; ?&gt;
&lt;/div&gt;
</pre>
<blockquote><p>Typisch weer een oplossing op mijn &#8220;slogan&#8221; gebaseerd: Waarom moeilijk doen als het makkelijk kan!</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/responsive-slider-in-wordpress-met-backend/">Responsive slider in WordPress met backend</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/responsive-slider-in-wordpress-met-backend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Icecat XML verwerken deel 2, de array weergeven</title>
		<link>https://royduineveld.nl/icecat-xml-verwerken-deel-2-de-array-weergeven/</link>
		<comments>https://royduineveld.nl/icecat-xml-verwerken-deel-2-de-array-weergeven/#comments</comments>
		<pubDate>Tue, 22 Jan 2013 16:53:43 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Icecat]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=298</guid>
		<description><![CDATA[<p>Hierbij het vervolg op mijn eerste bericht hoe een Icecat XML verwerkt kan worden. Het uitlezen is het &#8220;moeilijkste&#8221; stuk, het weergeven is gewoon een mooie layout maken en daar...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/icecat-xml-verwerken-deel-2-de-array-weergeven/">Icecat XML verwerken deel 2, de array weergeven</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Hierbij het vervolg op mijn eerste bericht hoe een <a title="Icecat XML verwerken" href="/icecat-xml-verwerken/" target="_blank">Icecat XML</a> verwerkt kan worden. Het uitlezen is het &#8220;moeilijkste&#8221; stuk, het weergeven is gewoon een mooie layout maken en daar de uitgelezen waardes in zetten.</p>
<h2>Foutafhandeling</h2>
<p>Om te beginnen, eerst maar even kijken of er geen fouten zijn.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// No icecat ID present?
if(!isset($data['id']))
{
	// Check for each error number and show the error
	if(isset($data[1]))
	{
		echo 'Error 1: '.$data[1];

	} elseif(isset($data[2]))
	{
		echo 'Error 2: '.$data[2];

	} elseif(isset($data[3]))
	{
		echo 'Error 3: '.$data[3];
	}
}
?&gt;
</pre>
<h2>Product informatie</h2>
<p>Zoals je hier al ziet wordt er elke keer gerefereerd naar $data, om dit niet steeds te hoeven doen is het meest makkelijke <a href="http://php.net/extract" target="_blank">extract</a> te gebruiken voor het weergeven van de product informatie. Wanneer er geen fouten zijn kunnen we verder:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;? extract($data); ?&gt;
&lt;h1&gt;&lt;?=$title;?&gt;&lt;/h1&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;SKU&lt;/th&gt;
		&lt;td&gt;&lt;?=$sku;?&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;th&gt;EAN&lt;/th&gt;
		&lt;td&gt;
			&lt;? foreach($ean as $e): ?&gt;
				&lt;?=$e;?&gt;&lt;br /&gt;
			&lt;? endforeach; ?&gt;
		&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;th&gt;URL&lt;/th&gt;
		&lt;td&gt;&lt;a href=&quot;&lt;?=$url;?&gt;&quot; target=&quot;_blank&quot;&gt;&lt;?=$url;?&gt;&lt;/a&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
</pre>
<p>Zo kan ik nog wel even doorgaan, dit spreekt voor zich natuurlijk. Hierna komen we de product afbeeldingen tegen, dit is uiteraard door een simpele <a href="http://php.net/foreach" target="_blank">foreach</a> te gebruiken, weer te geven. Nog wel een opmerking hierbij. Op het moment van schrijven geeft Icecat niet altijd alle formaten afbeeldingen mee aan producten. De thumbnail en de grote afbeeldingen worden altijd meegegeven, de kleine en middelmatige missen soms wel eens.</p>
<h2>Product specificaties</h2>
<p>Het gebruik van een &#8220;foreach&#8221; geldt ook voor de product specificaties maar laat ik daar wel een voorbeeldje voor maken gezien dit meestal het belangrijkste is:</p>
<pre class="brush: php; title: ; notranslate">
&lt;h2&gt;Product Specifications&lt;/h2&gt;
&lt;table&gt;
&lt;? foreach($spec as $id=&gt;$s): ?&gt;
	&lt;tr&gt;
		&lt;th title=&quot;Icecat specification category ID: &lt;?=$id;?&gt;&quot;&gt;&lt;?=$s['name'];?&gt;&lt;/th&gt;
		&lt;td&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;? foreach($s['features'] as $id=&gt;$f): ?&gt;
		&lt;tr&gt;
			&lt;td title=&quot;Icecat specification feature ID: &lt;?=$id;?&gt;&quot;&gt;&lt;?=$f['name'];?&gt;&lt;/td&gt;
			&lt;td&gt;&lt;?=$f['pres_value'];?&gt;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;? endforeach; ?&gt;
&lt;? endforeach; ?&gt;
&lt;/table&gt;
</pre>
<p>Alles kan natuurlijk uitgebreid en veel mooier gemaakt worden. Zo ook mijn kleine demo voor bij dit artikel:</p>
<p><a class="demo-button" href="https://royduineveld.nl/demos/icecat-xml/" target="_blank">Klik hier voor een online demo</a></p>
<blockquote><p>Als laatste nog even wat &#8220;sluikreclame&#8221; om een idee te geven wat er mogelijk is met de gegevens van Icecat. Bijvoorbeeld een <a title="WDB Trading" href="http://wdbtrading.nl" target="_blank">computer en toebehoren webshop</a> of website waar je <del><a title="Telbat - Tablets vergelijken" href="http://justtablets.nl" target="_blank">tablets kan vergelijken</a></del> (inmiddels offline maar de code staat op <a href="https://github.com/royduin/just-tablets" target="_blank">Github</a>).</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/icecat-xml-verwerken-deel-2-de-array-weergeven/">Icecat XML verwerken deel 2, de array weergeven</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/icecat-xml-verwerken-deel-2-de-array-weergeven/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Forbidden x-frame-options omzeilen</title>
		<link>https://royduineveld.nl/forbidden-x-frame-options-omzeilen/</link>
		<comments>https://royduineveld.nl/forbidden-x-frame-options-omzeilen/#comments</comments>
		<pubDate>Mon, 14 Jan 2013 22:01:25 +0000</pubDate>
		<dc:creator><![CDATA[Roy Duineveld]]></dc:creator>
				<category><![CDATA[Tips & Trucs]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">https://royduineveld.nl/?p=266</guid>
		<description><![CDATA[<p>Mocht je een pagina in een iframe laden en er komt niets tevoorschijn? Dan kan het zijn dat de volgende melding in de console staat: Refused to display document because...</p>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/forbidden-x-frame-options-omzeilen/">Forbidden x-frame-options omzeilen</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Mocht je een pagina in een iframe laden en er komt niets tevoorschijn? Dan kan het zijn dat de volgende melding in de console staat:</p>
<blockquote><p>Refused to display document because display forbidden by X-Frame-Options.</p></blockquote>
<p>Maar wat kan je eraan doen? In het geval dat je Google Maps wilt &#8220;embedden&#8221; in je website ben je waarschijnlijk &#8220;&amp;output=embed&#8221; vergeten in de url maar in alle andere gevallen wordt er veelal op het internet gezegd: pech, maar het kan niet. Om met een beter antwoord te komen, bij deze een &#8220;workaround&#8221;:</p>
<p>Laat ik het volgende bestand: iframe.php noemen:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
if($_GET['url']) {
 	echo file_get_contents($_GET['url']);
}
?&gt;
</pre>
<p>Vervolgens laden we de url voor het iframe via dit bestand:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;iframe src=&quot;iframe.php?url=http://website-welke-niet-wil-laden-in-een-iframe.nl/&quot;&gt;&lt;/iframe&gt;
</pre>
<p>En werken! Maar&#8230; zodra je op een link klikt kan het zijn dat het niet helemaal vlekkeloos gaat. Daar heb ik het volgende op bedacht:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * Huidge URL ophalen
 * @return string Volledige huidige url
 */
function curPageURL() {
	$pageURL = 'http';
	if ($_SERVER[&quot;HTTPS&quot;] == &quot;on&quot;){
		$pageURL .= &quot;s&quot;;
	}
	$pageURL .= &quot;://&quot;;
	if ($_SERVER[&quot;SERVER_PORT&quot;] != &quot;80&quot;){
		$pageURL .= $_SERVER[&quot;SERVER_NAME&quot;].&quot;:&quot;.$_SERVER[&quot;SERVER_PORT&quot;].$_SERVER[&quot;REQUEST_URI&quot;];
	} else {
		$pageURL .= $_SERVER[&quot;SERVER_NAME&quot;].$_SERVER[&quot;REQUEST_URI&quot;];
	}
	return $pageURL;
}

/**
 * Volledige url maken
 * @param  string $url  Huidige url
 * @param  array $host URL gegevens vanuit parse_url
 * @return string       Volledige url
 */
function nieuwe_url($url,$host)
{
	$scheme 	= $host['scheme']; //http of https
	$host 		= $scheme.'://'.$host['host'];

	if($url != '#' AND $url != '')
	{
		// Begint met &quot;//&quot; ?
		if(substr($url,0,2) == '//')
		{
			$url = $scheme.':'.$url;

		// Begint met &quot;/&quot; ?
		} elseif(substr($url,0,1) == '/')
		{
			$url = $host.$url;

		// Wat voor opties zijn er nog meer?
		} else {
			$url = $url;
		}

		$url = curPageURL().'?url='.$url;
	}
	return $url;
}

/**
 * En beginnen!
 */
if($_GET['url'])
{
	// Content ophalen
	$content 	= file_get_contents($_GET['url']);

	// Gegevens uit de url halen
	$url 		= parse_url($_GET['url']);

	// HTML in DOM laden
	$dom 		= new DOMDocument();
	@$dom-&gt;loadHTML($content);

	// Door alle &quot;a&quot; tags loopen
	foreach($dom-&gt;getElementsByTagName('a') as $linkjes)
	{
		// Href ophalen
		$href 	= $linkjes-&gt;getAttribute('href');
		// Nieuwe url ophalen uit functie
		$nieuw 	= nieuwe_url($href,$url);
		// Href verwijderen
		$linkjes-&gt;removeAttribute('href');
		// Nieuwe href toevoegen
		$linkjes-&gt;setAttribute('href', $nieuw);
	}

	// Het resultaat!
	echo @$dom-&gt;saveHTML();
}
?&gt;
</pre>
<blockquote><p>Ik heb dit niet getest met alle websites! Maar bij de meeste zou dit moeten werken. Daarnaast dit nog even: de x-frame-options zijn er niet voor niets, het gebruik van deze methode is dan ook op eigen risico natuurlijk.</p></blockquote>
<p>Het bericht <a rel="nofollow" href="https://royduineveld.nl/forbidden-x-frame-options-omzeilen/">Forbidden x-frame-options omzeilen</a> verscheen eerst op <a rel="nofollow" href="https://royduineveld.nl">Roy Duineveld</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://royduineveld.nl/forbidden-x-frame-options-omzeilen/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>