Archivo

Archivo para la categoría ‘English’

Roundcube 1.x Larry skin for netbook and tablets

Sábado, 30 de agosto de 2014

Roundcube is a very good mail client but suffers from waste of screen space

The rant:
Now I hate, i really hate this new fashion of making screens one inch high 10 feet wide.
Specially as microsoft for example has not realized that and proposes office with a toolbar that is like 2 inched wide and is horizontal… Arghhh… Forget word and a Netbook for example.

Finally to the point:
The default Larry skin that comes with roundcube is beautiful but has a lot of wasted horizontal space and i hated to check mails in my tablet or netbook, I looked around but everybody seems to charge for the skins and you can’t really test them to see if they satisfy your needs.

So i took a bit ofmy time and did my best (I’m no programmer or anything but know my way around css) and created an extension of Larry skin removing or repositioning stuff to gain some horizintal space.

Also I tried my best to take advantage of the portrait orientation mode of what tablet i could get my hands to test.

Also I tried to modify the less possible number of files to keep stuff simple (6 files).
Some core functions blocked me from implementing some ideas I had as I did not wanted to mess with core files.

I’m sure that someone who knows roundcube better than I do can make a better job, but it fits my needs as is and I wished to give something back so I’m releasing it in my site.

Just download it and put it in your skins folder, then activate it on the preferences.

If someone decides it is useful and is willing to enhance it I will appreciate if he/she shares the result for free, but that is up to you.

Here is the link: Larry-netbook

Capture


Author: Categories: English Tags:

Solution to: WP 3.5 “An error occurred in the upload. Please try again later.”

Lunes, 23 de diciembre de 2013

Originally posted on the 28th of january 2013, updated with a new finding on december 2013.


 

UPDATE december 2013: the problem came back on 3.6 or 3.7 I dug more in the possible cause and found another possibility.

Closing PHP tags inside the functions.php file and reopening them will produce this error too… 

in my case i was using it to write html as part of a function as it is easier to escape the quotes in html than php.


If after upgrading to WordPress 3.5 you cannot insert images follow this steps:

  • Start by disabling all the plugins. (I know you already did it but bear with me)

Try now uploading.

If it worked then you have a problem with plugins (Go read  1 below)   /    If that doesn’t work, leave them disabled.

  • go to your theme folder and rename the functions.php to whatever name you want.

Try uploading now…

If it worked then you have a problem with your functions (Go read 2  below)

 If that doesn’t work neither and you are using a child theme make sure there is no functions.php on the parent theme folder

(if you don’t know what i am speaking about leave a comment and i will help you by email).

  • Still don’t work, what do I do now ?.

This problem is mainly caused by Java Script / jQuery conflicts between core WordPress and custom code you installed in your blog for plugins or functions you got from the Internet.

The implementation of Java Script in WordPress is complicated to say the least…

Java Script is difficult to troubleshoot unless you are a JS developer and then you would not be reading this…

(Go read 3 below)

1 .- PLUGINS trouble shooting:

  • You should have done this already there are plenty of posts in WP support…
  • Disable all the plugins and re-enable them one by one until the uploader breaks.
  • If disabling the plugins dont fix your uploader, Rename your Plugins folder and try to upload to see if that fixes it.

2 .- FUNCTIONS.PHP

  • Make sure you don’t have any lines with comments in HTML mark up (Example <!– I am a HTML code comment –> )
  • Make sure you open and close the PHP tags ONLY ONCE!!! in the file.

that fixed my uploader.

3.- JavaScript Problems

The reason there is not much support for this problem is because WordPress works, and the problem is coming from something you or your theme developer broke.

Lets start with some basic troubleshooting: (You have Chrome and / or Mozilla installed don’t you ? )

  • First Step: Chrome; go to the home page of your WordPress blog.

Right click anywhere on the screen and on the menu that pops click on inspect element this will open a pseudo-window  with information about your page source code etc…

In the bottom right of this window there is a cog (gear)  icon and next to it a little red circle with a white x on it, next to that usually is a number (That lists parsing errors when your page loaded.

If you have any number next to the red circle click on it to see the detail of the error.

You can ignore any Port error: bla bla (this don’t break the uploader and is another different matter).

IGNORE: Port error: Could not establish connection. Receiving end does not exist.

If you have 404 errors listed this means that you are missing some files, this is not usually the culcript but you should try to solve those because is not good anyway.

We are interested in Java Script errors usually something like this:

Uncaught TypeError: Object function (a,b){return new e.fn.init(a,b,h)} has no method ‘widget’ jquery-ui-interactions.js:13
If you dont see anything here do your best to keep both your blog and this Developer Tools Window visible and navigate to your wp-admin page, always keeping an eye on the errors on the other window.
Try to upload and see if you get any errors.
Usually the errors that break the uploader show in the front page and not in the back-end.
What you need to do is keep an eye in the JavaScript errors in the front-end because once JS finds an error it stops executing the rest of the scripts on the page.
Last bit of advice:
The most common reason for this to happen is that someone is calling somewhere the jQuery libraries and WordPress calls its own tested version of jQuery, calling jQuery twice specially different versions slows down your page, and also can break the delicate balance of WordPress and the universe.
WordPress calls jQuery only when it needs it, and if you added somewhere in your theme or template a call to jQuery the uploader will break.
If none of these steps helped you fix your uploader drop a note here, I will try to check your site and give you some personal advice (time permits)
If I helped leave a comment it feeds my ego and makes me feel better

Author: Categories: English Tags:

Mod for Roundcube CSS to use better screen space

Lunes, 4 de febrero de 2013

RoundCube is a good Webmail client, but the default skin leaves much to be desired.

In these ages of 1000/9 screens were you get 1 inch high, 3 miles wide screens, use 360 pixels to display a logo and 3 buttons is just bad practice.

Happily by changing a few lines in the CSS files you can solve this.

Roundcube - Css - Hack

Roundcube - Css - Hack

  1. Logo becomes 1px * 1px big so is invisible
  2. Search fields take the old Logo position
  3. The buttons now are shown on hover
  4. bottom margin changed from 20px to 0 as is not used to display anything

this means you recover 240 pixels height. Very important on Netbooks or Tablets with a  resolution of 1024*600px.

 

 

 

 

How to do it ?:

Done!…

If you don’t trust my CSS get it and see the changes, sorry i’m too lazy to have documented them.

Remember to keep a copy of your original files!


Author: Categories: English Tags:

Epson All in one Stylus SX-425-W Troubleshooting (problem Scanning on WIFI)

Jueves, 31 de enero de 2013

Epson Built to perform, just not as expected

After spending 2 days installing and re installing the driver, calling technical support, dealing with the stupid interface for chatting with Epson UK (Seriously, the chat window is not re-sizable  if you zoom the browser the text disappears  and also they can push files directly to your PC) but one image says more than a thousand swords… (I wish i had one sword i mean).

Everything worked in the printer, except  the scanner button , if i tried to scan from the PC it would work, it would print.. All good… but Scan to PC from the Printer will return a bloody code W-21

After 1 hour on that tiny horrid chat, time spent basically redoing every single thing I had done for the last 2 days (and the expense report still awaiting its attachments), the Tech Representative (who claim to be called Rachael, but i heavily suspect something in the lines of Sanjey, I must say before making it work i had to restart the PC and lost the Chat with Rachel/Rachaid… Windows restarts First thing i do is test the scanner and ! Yes it works!!Vinay or Rashid…) pushed me a version of the Epson Event Manager, this thing apparently comes with drivers bundled… After 3 failed attempts to install on Windows 7 it finally worked.

I look at my tray and i have 3 instances of the Event-manager, three instances of the other shit that tries to sell you  Ink and what not…

So I remove the three Epson printers that I don’t have and kept what looked like the latest one.

Well I kept one that doesn’t not only wont scan but also wont print…

Uninstalled all the bundled software that comes with the printer (Which is a effing lot) and re installed from the CD, after that  Ran the Event manager Rachid pushed to my PC, restarted windows and Voila!.. NO… don’t work…

Finally i found the solution and it takes only a few steps:

  1. Disconnect the printer (all cables, everything)
  2. Put it on a hard flat surface
  3. Jump on top it
  4. If still in 1 piece go get a hammer (that should suffice, else get a sledge hammer)
  5. Go to your Computer Hardware  Store and get a real printer from any other brand, anyway nodaways the printer is cheaper than the Ink

That’s all your printer should work as intended now, and the best of all you wont need Rashid and his stupid chat window anymore


WordPress 3.51 the proper way to get custom avatars

Miércoles, 30 de enero de 2013

WordPress does not have an option to remove calls to gravatar.com, nor to set default site avatars or add custom user avatars outside gravatar.com Many people claims that calls to gravatar.com slow down the sites and some are just bored of the silly default mystery man or the monsters. You can disable Avatars completely but this plugin adds functionality to set your custom avatar and the site default one.

Buy me a beer

Previously I had created a code for my functions.php in my theme see here but then I upgraded to 3.51 and it worked but in the back end there where some problems.

Also I realized I was not protecting the input fields against injections which is a very bad thing.

So I did the sensible thing and started coding again, I ended up making a plugin out of it.

This plugin adds the following functionality:

  1. Show Avatars
  2. Remove calls to gravatar.com
  3. Use local default Avatar
  4. Add custom avatar for the blog users
  5. Display Custom avatar for blog users
  6. Display default avatar for unregistered commenter
  7. Display custom avatar for comment replies

Installation:

  1. Extract the download on your computer and upload the proper-avatars folder to wp-content/plugins/.
  2. Enable the plugin from the ‘Plugins’ page.
  3. Go to settings -> discussion; Scroll down to the option to set the site wide default avatar
  4. type or Paste the URL of the Avatar image you would like to use in the field
  5. Go to your user profile and add the url to your avatar (Every user can do that)
  6. type or Paste the URL of the Avatar image you would like to use in the field
Get it now!

Author: Categories: English Tags:

WordPress 3.4 and higher Custom Avatars the proper way

Domingo, 27 de enero de 2013

There is a new version of this that works with 3.51 read it here:  WordPress 3.51 the proper way to get custom avatars
There are about 1 million results in google to implement avatars, local avatars, remove gravatars, some even explain how to turn off all avatars from the back-end.

I had this project where i needed to:

  • Show Avatars
  • Remove calls to gravatar.com
  • Use local default Avatar
  • Add custom avatar for the blog users
  • Display Custom avatar for blog users
  • Display default avatar for unregistered commenter
  • Display custom avatar for comment replies


Buy me a beer

Digging for 3 days around google got me two posts which gave me the initial code:

Add default Custom Avatar: http://studio412design.com/custom-default-avatar-for-wp-comments

Custom Avatar Field by Bill Erickson: http://www.billerickson.net/wordpress-custom-avatar/

However the first one only allows to define a custom local default avatar. (Still calls gravatar.com and if nothing found displays a local image)
The second one only works properly on pages, while on comments shows the avatar of the author of the page for unregistered commenter.

During a few days struggling with code examples that did not completely solve my problem I decided to develop a solution myslef.
I dug into wp-includes/pluggable.php and after a struggle understood how WordPress was calling the avatars and what needed doing to get the results I wanted.

No core files should be modified and that was the hardest part.

So I came up with a nice modification in functions.php which i decided to convert in a plugin for the less savvy users.

To use it:

  • Download the file
  • extract the ZIP (1 folder: proper-avatars containing 2 files readme.txt and proper-avatars.php)
  • copy the folder to your /wordpress/wp-content/plugins folder
  • go to the admin area and start defining avatars for your users (the field is added at the end of user profiles)

Alternatively: copy the code at the end of the article in your functions.php file in your theme folder

The demo is available  on the main site: http://rockdio.org

<!--?php /* Plugin Name: Proper Custom Avatars Plugin URI: http://rockdio.org/ayudatech/wordpress-3-4-and-higher-custom-avatars-the-proper-way/ Description: Proper way of displaying Custom avatars, remove calls to http://gravatar.com, Use local default Avatar, Add custom avatar for the blog users,Display Custom avatar for blog users, Display default avatar for unregistered commenter, Display custom avatar for comment replies. Version: 0.1.0 License: GPL Author: Nathaniel Narvaez (RockDio.org) Author URI: http://rockdio.org */ /*===================================================================================  * Add default Custom Avatar   * @ http://studio412design.com/custom-default-avatar-for-wp-comments  * =================================================================================*/ add_filter( 'avatar_defaults', 'newgravatar' ); function newgravatar ($avatar_defaults) { $myavatar = get_bloginfo('stylesheet_directory').'/imagenes/escucha.jpg';		// Change this to point to where your custom 												// avatar is stored $avatar_defaults[$myavatar] = "Avatar de Rockdio"; 					// Change this to describe your Default Avatar return $avatar_defaults; }  /*===================================================================================  * Use Custom Avatar if Provided  * If no Avatar is found the default from the function above is used  * =================================================================================*/ function be_gravatar_filter($avatar, $id_or_email, $size, $default, $alt) { 	if (!is_object($id_or_email)) { 												//Returns the Local Avatar for Posts and Pages 			$custom_avatar = get_the_author_meta('be_custom_avatar'); 			if(!empty($custom_avatar)) 			$avatarfound = $custom_avatar; 			elseif(empty($custom_avatar)){ 												//Returns the Local Avatar for ADMIN AREA  				$id = $id_or_email; 				$custom_avatar = get_user_meta($id,'avatar',true);   				if(!empty($custom_avatar)){ 				$avatarfound = $custom_avatar; 				} 			} 		} 	elseif ( !empty($id_or_email--->user_id) ) {
												//Returns the Local Avatar for Comments
			$id = (int) $id_or_email->user_id;
			$user = get_userdata($id);
			if ( $user){
												//Returns the Local Avatar for comments if User has one
				$email = $user->user_email;
				$custom_avatar = get_user_meta($user,'be_custom_avatar',true);
				$avatarfound = $custom_avatar;
			}
		}
	elseif ( !empty($id_or_email->comment_author_email) ) {
												//Returns the DEFAULT Local Avatar for comments
			$email = $id_or_email->comment_author_email;
			$avatarfound = $default;
		}

	if ($avatarfound =='')
			$avatarfound = $default;

	$avatar = "</pre>
<img class="avatar avatar-{$size} photo" src="{$avatarfound}" alt="{$safe_alt}" width="{$size}" height="{$size}" />
<pre>";
	return $avatar;

}
add_filter('get_avatar', 'be_gravatar_filter', 1, 5);
//
print_r($custom_avatar)

/*===================================================================================
 * Add Custom Avatar Field @param object $user
 * @link http://www.billerickson.net/wordpress-custom-avatar/
 * =================================================================================*/
function be_custom_avatar_field( $user ) { ?></pre>
<h3>Custom Avatar</h3>
<table>
<tbody>
<tr>
<th><label for="be_custom_avatar">Custom Avatar URL:</label></th>
<td>
<input id="be_custom_avatar" style="width: 400px;" type="text" name="be_custom_avatar" value="<?php echo esc_attr( get_the_author_meta( 'be_custom_avatar', $user->ID ) ); ?>" />

 <span>Type in the URL of the image you'd like to use as your avatar. This will override your default Gravatar, or show up if you don't have a Gravatar.
<strong>Image should be 70x70 pixels.</strong></span></td>
</tr>
</tbody>
</table>
<pre>	<!--?php  } add_action( 'show_user_profile', 'be_custom_avatar_field' ); add_action( 'edit_user_profile', 'be_custom_avatar_field' );   /*===================================================================================  * Save Custom Avatar Field @param int $user_id @author Bill Erickson  * @link http://www.billerickson.net/wordpress-custom-avatar/  * =================================================================================*/ function be_save_custom_avatar_field( $user_id ) { 	if ( !current_user_can( 'edit_user', $user_id ) ) { return false; } 		update_usermeta( $user_id, 'be_custom_avatar', $_POST['be_custom_avatar'] ); } add_action( 'personal_options_update', 'be_save_custom_avatar_field' ); add_action( 'edit_user_profile_update', 'be_save_custom_avatar_field' ); ?-->

Author: Categories: English Tags:

WordPress editor text area is too big? Solution

Miércoles, 26 de diciembre de 2012

For some reason since i upgraded to version 3.5 the bloody text editor is a million lines long… there was no solution to it, it was not the theme, was not the template, something was wrong with my WP.

I dug into the core files and found this:

Edit: /wp-includes/class-wp-editor.php

Look for this code (on Line 72)

if ( $set['editor_height'] < 50 )
$set['editor_height'] = 50;

Line 74 and 75 should be something like this:

elseif ( $set['editor_height'] > 5000 )
$set['editor_height'] = 5000;

Try changing line 74 and 75 to something like this:

elseif ( $set['editor_height'] > 500 )
$set['editor_height'] = 500;

Done! now your editor has a decent size


Author: Categories: English Tags:

WordPress editor Solution to line break removal

Miércoles, 26 de diciembre de 2012

The pesky WordPress editor insists in removing line breaks, however there is an easy solution, but it is difficult to find.

This works on WP version 3.5 and higher.

There are solutions on the web using unmaintained plug-ins or instructions for old versions of wordpress.

Apparently the reason is that HTML does not like line breaks… so much for a WYSIWYG editor…

Edit your functions.php file located in:

wp-content/themes/<your-theme>/

Add the following code at the beggining after the php tags:

function myformatTinyMCE($in)
{
$in['remove_linebreaks']=false;
return $in;
}
add_filter(‘tiny_mce_before_init’, ‘myformatTinyMCE’ );

Save and done, your line breaks will be replaced by

&nbsp;


Asus P6T and IDE to AHCI ends in BSOD

Sábado, 2 de junio de 2012

If you have a ASUS Mobo a P6T especifically and change the storage setting from ide to AHCI the result will be WINDOWS 7 (maybe other flavors neither) will not start/boot showing a blue screen of death (BSOD) upon loading.

It took me 5 hours of system restore, image loading and bootrec.exe /fixmbr /fixboot /RebuildBcd to realize this seting had been changed in the bios of the asus motherboard.

This happened  while i was trying to dual boot ubuntu and 7 from the same disk.

Moral: go back to pencil and paper and forget this bloody personal computers… or dont touch them… they make a nice sculpture in your living room.

The easiest way to dual boot ubuntu and windows is to install ubuntu in a different phisical hard disk and choose a boot device using F8 feature on asus mother boards.

I am so fucking enraged… as now for some reason windows says is not genuine…thou it starts…

 

 


Author: Categories: English Tags:

CentovaCast reccenttracks.js auto update with fadein and fadeout effect, using Jquery

Martes, 24 de abril de 2012

After a lot of struggle with the insuficient and undocumented widget from centovacast and putting away my feelings about their decision to obfuscate their php code i finally managed to modify the javascript on the reccenttracks.js file in order to:

a) Remove the album art (most of the times it shows either empty or the wrong one…)
b) Make the bloody script auto refresh every 60 seconds to update the last 10 songs played.

here is the JS code if you so like…

function cc_recenttracks_add(ncon,track,first)
{var ntrk=document.createElement('div');
ntrk.className='cctrack';
var ntit=document.createElement('txt');
ntit.className='cctitle'+(first?' ccnowplaying':'');
ntit.innerHTML='&amp;lt;/pre&amp;gt;
&amp;lt;ul&amp;gt;
	&amp;lt;li&amp;gt;&amp;lt;em class=&amp;quot;&amp;amp;quot;ccartist&amp;amp;quot;&amp;quot;&amp;gt;'+track.title+'&amp;lt;/em&amp;gt;    &amp;lt;strong&amp;gt;by:&amp;lt;/strong&amp;gt; '+track.artist+'&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;pre&amp;gt;

';ntrk.appendChild(ntit);
var nart=document.createElement('txt');
nart.className='ccartist';
/*nart.innerHTML='By:  '+track.artist+'

';*/
ntrk.appendChild(nart);
ncon.appendChild(ntrk);
}
function cc_recenttracks_get_callback(tracks,selfurl){
var ccrte=document.getElementById('cc_recent_tracks');
if(!ccrte)return;ccrte.innerHTML='';for(var i=0;i}
var auto_refresh = setInterval(
function()
{
$('#cc_recent_tracks').fadeOut(5000, function() {$('#cc_recent_tracks').load('refresh.html').fadeIn(5000);})
}, 60000);

create a file named refresh.html and paste your centovacast code for querying the last songs in example:
refresh.html

&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;javascript&amp;quot; src=&amp;quot;http://metalon.rockdio.org/cast/js.php/metalonheavy/recenttracks/rnd0&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

Also need to invoque jquery from your header… but nodaways most likely it is already invoqued

&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

Here is an example with all the html you should need…


&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;javascript&amp;quot;&amp;gt;// &amp;lt;![CDATA[
function cc_recenttracks_add(ncon,track,first)
{var ntrk=document.createElement('div');
ntrk.className='cctrack';
var ntit=document.createElement('txt');
ntit.className='cctitle'+(first?' ccnowplaying':'');
ntit.innerHTML='
	&amp;lt;li&amp;gt;&amp;lt;em class=&amp;quot;ccartist&amp;quot;&amp;gt;'+track.title+'&amp;lt;/em&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;strong&amp;gt;by:&amp;lt;/strong&amp;gt;  '+track.artist+'&amp;lt;/li&amp;gt;

';ntrk.appendChild(ntit);
var nart=document.createElement('txt');
nart.className='ccartist';
/*nart.innerHTML='By:  '+track.artist+'&amp;lt;/li&amp;gt;

';*/
ntrk.appendChild(nart);
ncon.appendChild(ntrk);
}
function cc_recenttracks_get_callback(tracks,selfurl){
var ccrte=document.getElementById('cc_recent_tracks');
if(!ccrte)return;ccrte.innerHTML='';for(var i=0;i&amp;lt;tracks.length;i++){cc_recenttracks_add(ccrte,tracks[i],i==0);}
}
var auto_refresh = setInterval(
function()
{
$('#cc_recent_tracks').fadeOut(5000, function() {$('#cc_recent_tracks').load('refresh.html').fadeIn(5000);})
}, 60000);
// ]]&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;/pre&amp;gt;
&amp;lt;h2&amp;gt;Widget Test&amp;lt;/h2&amp;gt;
&amp;lt;h4&amp;gt;SONG HISTORY&amp;lt;/h4&amp;gt;
&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;hr /&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;div id=&amp;quot;cc_recent_tracks&amp;quot; style=&amp;quot;text-align: left; min-height: 250px;&amp;quot;&amp;gt;Loading...&amp;lt;/div&amp;gt;
&amp;lt;pre&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;javascript&amp;quot; src=&amp;quot;http://metalon.rockdio.org/cast/system/recenttracks.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;javascript&amp;quot; src=&amp;quot;http://metalon.rockdio.org/cast/js.php/metalonheavy/recenttracks/rnd0&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;div style=&amp;quot;font-size: 0.5em; color: #fff;&amp;quot;&amp;gt;

&amp;lt;hr /&amp;gt;

@ 2012, Developed by: &amp;lt;a href=&amp;quot;http://rockdio.org&amp;quot;&amp;gt;Nathan IMAIDEN (AKA the Wizard)&amp;lt;/a&amp;gt; for: &amp;lt;a href=&amp;quot;http://metalon.org&amp;quot;&amp;gt;RadioMetalOn&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;pre&amp;gt;

Dont forget to create refresh.html