Sk8erPeter képe

Form API-t tudod kezelni saját sminkből vagy modulból? Mert akkor könnyű a dolog, egy megfelelő hook_form_alter()-ben csak hozzáadod az adott formelemhez a
'#placeholder' => t('Enter your name here'),
kulcsot a megfelelő formmezőhöz.
Egyébként nem tudom, mennyire szükséges egyáltalán a Placeholder modul használata, gondolom ez max. annyit tesz hozzá, hogy amikor a júzer a formelemre klikkel, akkor tűnjön el a placeholder... ez nem biztos, hogy indokolt.

OFF bekapcs.:
vicces, hogy a projekt oldalán azt mondja:

"This project adds an extra FAPI attribute called '#placeholder' to textfield field elements. Often textfields should have some text in them like "Enter your text here" until the user clicks on (or tabs to) the element in question. At that point, the text should disappear and the user can enter his or her desired input.

Take a look at the "Search Drupal.org" text in the search box at the top of this page to see what I'm talking about :)"

Kár, hogy ez butaság, mert a drupal.org-os kereső pont nem úgy működik, hogy amikor az ember belekattint, akkor eltűnik a "Search drupal.org", hanem csak egy mezei placeholder attribútum van hozzáadva:
<input type="text" maxlength="128" name="search_theme_form" id="edit-search-theme-form-1" size="15" value="" placeholder="Search drupal.org" class="form-text">
ami épp az ezt az attribútumot támogató böngésző beépített magatartása szerint viselkedik, tehát hogy csak akkor tűnik el a szöveg, amikor elkezdünk a formelembe gépelni. :))
/OFF kikapcs.

Form API használata esetén ugyanis nagyon egyszerű a placeholdert hozzáadni, pl. egy saját theme_textfield()-ben ennyi:

  1. /**
  2.  * Returns HTML for a textfield form element.
  3.  *
  4.  * @param $variables
  5.  * An associative array containing:
  6.  * - element: An associative array containing the properties of the element.
  7.  * Properties used: #title, #value, #description, #size, #maxlength,
  8.  * #required, #attributes, #autocomplete_path.
  9.  *
  10.  * @ingroup themeable
  11.  */
  12. function SMINKEDNEVE_textfield($variables) {
  13. $element = $variables['element'];
  14. $element['#attributes']['type'] = 'text';
  15. element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
  16. _form_set_class($element, array('form-text'));
  17.  
  18. if(isset($element['#name']) && $element['#name'] == 'mail'){
  19. $element['#attributes']['placeholder'] = '[email protected]';
  20. }
  21. else{
  22. // pl. switch user block autocomplete mezőjénél nincs beállítva a #title
  23. $element['#attributes']['placeholder'] = isset($element['#title']) ? $element['#title'].'...' : '';
  24. }
  25.  
  26. $extra = '';
  27. if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
  28. drupal_add_library('system', 'drupal.autocomplete');
  29. $element['#attributes']['class'][] = 'form-autocomplete';
  30.  
  31. $attributes = array();
  32. $attributes['type'] = 'hidden';
  33. $attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
  34. $attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE));
  35. $attributes['disabled'] = 'disabled';
  36. $attributes['class'][] = 'autocomplete';
  37. $extra = '<input' . drupal_attributes($attributes) . ' />';
  38. }
  39.  
  40. $output = '<input' . drupal_attributes($element['#attributes']) . ' />';
  41.  
  42. return $output . $extra;
  43. }

Ez most persze csak egy lehetőség a sokból, de szerintem a legegyszerűbb; ez annyit csinál, hogy minden mail szövegmezőbe a yourname@example.com stringet fogja belepakolni placeholderként, minden egyéb szövegmezőbe pedig a formelem címét, három ponttal, amennyiben a title be van állítva. Természetesen feltételekhez is lehet kötni ezt az egészet, tehát lehet olyat is, hogy csak bizonyos formelemeknél legyen egyáltalán placeholder, vagy alapból mindegyiknél legyen, kivéve az XYZ mezőket.
DE ha ezt használod, akkor érdemes tudni róla, hogy ez így sminkfüggő, viszont a Placeholder modul használata esetén sminktől függetlenül is lesznek placeholdereid.

2
0
aboros képe

nincs lehetetlen. :)

a node images egy szép sminkhurkot ad ami összeállítja neked azt a stringet, ami majd a node.tpl.php -ban a $node->node_images lesz.
ezt, mint minden sminkhurkot (theme_ kezdetű függvény bármilyen modulban) újra megvalósíthatod a template.php -ben (ez a te sminked része, ha nincs ilyen file benne, hozzad létre kézzel). az a szabály, hogy pl a theme_world_alter hurkot SMINKEDNEVE_world_alter néven kell megvalósítanod.

a szóban forgó függvény a theme_node_images_view, node_images.module 730. sor..
(ha nem világos, hogy derítettem ezt ki, légyszi kérdezz rá, szívesen elmagyarázom)

szóval azt a függvényt ami ott van, egyszerűen kimásolod és beilleszted a sminked template.php -jába.

ezután ilyenre szerkeszted (vagy eleve ezt kopizod be:)

/**
 * Show node images in the node view.
 */
function SMINKEDNEVE_node_images_view($node, $teaser, $page, $block = FALSE, $count = NULL, $format = NULL) {
  if (arg(2) == 'image_gallery' || empty($node->node_images)) return;
 
  $output = '';
  $i = 0;
 
  // set maximum number of images for teaser/body
  $view = ($teaser ? 'teaser' : 'body');
  if (!$count) {
    $count = variable_get('node_images_'.$view.'_images_'.$node->type, 2);
  }
  if (isset($count) && $count == '0') return;
 
  // set image format
  if (!$format) {
    $format = variable_get('node_images_'.$view.'_format_'.$node->type, 'thumbs');
  }
 
  foreach((array)$node->node_images as $id => $image) {
    $description = check_plain($image->description);
    $pattern = '<img src="%path" alt="%description" /><span class="node-images-filename">%filename</span>';
    $thumb = strtr($pattern, array('%path'=>file_create_url($image->thumbpath), '%description'=>$description, '%filename'=>$image->filename));
    $fullsize = strtr($pattern, array('%path'=>file_create_url($image->filepath), '%description'=>$description));
 
    if ($info = @getimagesize($image->filepath)) {
      $width = $info[0] + 36;
      $height = $info[1] + 36;
    }
    else {
      $width = 420;
      $height = 315;
    }
 
    if ($format == 'thumbs') {
      $output .= '<a href="javascript:void(0);" title="'.$description.'" onclick="window.open(\''.
        file_create_url($image->filepath).'\', \'\', \'height='.$height.',width='.$width.'\');">'.$thumb.'</a> ';
    }
    else {
      $output .= $fullsize.' ';
    }
    if ($count>0 && ++$i >= $count) break;
  }
 
  if ($block && $count < count($node->node_images)) {
    $output .= '<div class="node_images_block_link">'.l(t('View all images'), 'node/'.$node->nid.'/image_gallery').'</div>';
  }
 
  return $output;
}

(a SMINKEDNEVE részt ugye átírod a saját sminked nevére)
kész is vagyunk, mentjük az állllományt :P és ürítjük a smink regisztrációs tárat, jó étvágyat. ez fog történni ugye: http://skitch.com/aboros/np6q9/add-filename-to-node-images

figyedoda, hogy az eredetihez képest csak itt nyúltunk bele:

$pattern = '<img src="%path" alt="%description" /><span class="node-images-filename">%filename</span>';
$thumb = strtr($pattern, array('%path'=>file_create_url($image->thumbpath), '%description'=>$description, '%filename'=>$image->filename));

egyszerűen csak hozzáadtuk a mintához és a "thumbhoz" is a nekünk kellő dolgot, szevasz.
ez minden tartalom típusban, ami használ node imagest, ezt fogja csinálni. hogy hogy néz ki, az ugye css kérdése. cserélgetheted a spant divre, meg pakolhatsz köré amit akarsz, lelked rajta ;)

bár a node images úgy néz ki sokat fejlődött, meg igazán jópofa modul, rugalmasságban, ezáltal jövőállóságban a megközelítése nem veheti fel a versenyt a filefield+imagefield+imagecache trióval. (ha más nem: fields in core! jippiájjé)

minden ami saját "mezőket" ad hozzá a nodehoz úgy, hogy az nem cck, előbb utóbb felesleges lesz. (ez a magánvéleményem)

azt javaslom, hogy bár a probléma megoldódott, gondold át, hogy mégiscsak kell e neked ez a modul erre a feladatra. ha csak azért kell, mert saját fülre pakolja a képfeltöltést, vagy mert .. áhh, el se tudom képzelni miért kell. :) mitől olyan vonzó?

0
0

-
clear: both;

Sweetchuck képe

Az elmúlt hetekben több fórum téma is született a felhasználói profilokkal kapcsolatban. Érdemes lenne azokat átolvasnod.
Jelen topikod alapján, nem értem hogy egy felhasználó hogyan tudja megadni magárol hogy melyik nemhez tartozik.
-----

A kérdésed megoldásához a felhasználói nevek megjelenítését végző smink függvényt kell módosítani.
theme_username()
A kód amit küldök az kizárólag csak a te egyedi esetedre fog müködni!
A web helyeden használt sminknek a könyvtárában van egy olyan fájl hogy: template.php
A végéhez hozzá kell adni ezt:

function garland_username($object) {
  if ($object->uid && $object->name) {		
		// Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }
 
    if (user_access('access user profiles')) {
			//A roles tömb akkor is létezik ha nem betöltött USER objebjektumról van szó, de akkor csak 1 csoportot tartalmaz.
			//A roles tömb nem létezik NODE object esetén.
			//$object = user_load($object);
			if ( !array_key_exists('roles', $object) OR count($object->roles) < 2)
			{
				$object->roles = array(DRUPAL_AUTHENTICATED_RID => 'authenticated user');			
				$result = db_query('SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d', $object->uid);
				while ($role = db_fetch_object($result)) {
					$object->roles[$role->rid] = $role->name;
				}
			}
			$role_id_male = 16;
			$role_id_female = 15;
			$attributes = array('title' => t('View user profile.'));
 
			if ( array_key_exists($role_id_male, $object->roles) ) 	{
				$attributes['class'] = 'male';
			}
			else if ( array_key_exists($role_id_female, $object->roles) ) {
				$attributes['class'] = 'female';
			}
      $output = l($name, 'user/'. $object->uid, $attributes);
    }
    else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if (!empty($object->homepage)) {
      $output = l($object->name, $object->homepage, array('rel' => 'nofollow'));
    }
    else {
      $output = check_plain($object->name);
    }
 
    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', t('Anonymous'));
  }
 
  return $output;
}

Egy kicsit változtatni kell rajta. Ez első sora jelenleg így néz ki:
 function garland_username($object) {
A garlad helyére a te sminked nevét kell írni. Tehát:
 function atesminkedneve_username($object) {

---
 function phptemplate_username($object){
jobb megoldás, ha phptemplate-t használunk, mert így kényelmesebb lesz az életünk, ha átnevezzük a sminket, vagy alsminket alakítunk ki.

pp
---

(Ha már volt ilyen függvény akkor bukik az egész.)

Szintén a sminked könyvtárában van egy olyan fájl hogy: style.css
Annak a végére pedig add hozzá ezt:

a:link.female {
	background-color: pink;
}
a:link.male {
	background-color: #c0e0f4;
}

Ez csak példa a dizájnra. Izlés szerint lehet rajta változtatni.
(Böngésző gyorstárazás megviccelhet)

Remélem jó lesz.

0
0
aboros képe

láthatod a zen page.tpl.php -jában, hogy az elsődleges hivatkozásokat így írja ki:

<?php if ($primary_links): ?>
  <div id="primary">
    <?php print theme('links', $primary_links); ?>
  </div> <!-- /#primary -->
<?php endif; ?>

úgy tudsz beavatkozni, hogy a sminked template.php -jában saját theme_links eljárást csinálsz az eredeti alapján, amit megtekinthetsz az api.drupal.org -on.
http://api.drupal.org/api/function/theme_links/6

mutatom:

function SMINKNEVE_links($links, $attributes = array('class' => 'links')) {
  global $language;
  $output = '';
 
  if (count($links) > 0) {
    $output = '<ul'. drupal_attributes($attributes) .'>';
 
    $num_links = count($links);
    $i = 1;
 
    foreach ($links as $key => $link) {
      $class = $key;
 
      // Add first, last and active classes to the list of links to help out themers.
      if ($i == 1) {
        $class .= ' first';
      }
      if ($i == $num_links) {
        $class .= ' last';
      }
      if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))
          && (empty($link['language']) || $link['language']->language == $language->language)) {
        $class .= ' active';
      }
      $output .= '<li'. drupal_attributes(array('class' => $class)) .'>';
 
      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
 
#figyelj, itt kell neked beleturni, hogy ne csak egy link legyen hanem legyen korulotte megegy elem amit celozhatsz. 'b' helyett inkabb egy 'span' -ba foglaljuk most a linkedet.
        $link['html'] = TRUE;
        $output .= l('<span>'.$link['title'].'</span>', $link['href'], $link);
      }
      else if (!empty($link['title'])) {
        // Some links are actually not links, but we wrap these in <span> for adding title and class attributes
        if (empty($link['html'])) {
          $link['title'] = check_plain($link['title']);
        }
        $span_attributes = '';
        if (isset($link['attributes'])) {
          $span_attributes = drupal_attributes($link['attributes']);
        }
        $output .= '<span'. $span_attributes .'>'. $link['title'] .'</span>';
      }
 
      $i++;
      $output .= "</li>\n";
    }
 
    $output .= '</ul>';
  }
 
  return $output;
}

így.
persze ez minden linkedet spanok közé rakja majd, ami lehet baj, lehet nem. ha baj és te csak és kizárólag a primary linksre akarod ezt, akkor nevezd mondjuk my_primary -nek a függvényt és a page.tpl.php -ban azt hívjad a kiíráshoz, ne az eredeti theme('links'.. hívást.

0
0

-
clear: both;

v-to képe

ckeditor vagy szűrő baj lesz!

Kínlódásom ezen fázisában beírtam egy cikkbe ezt fullhtml formátumban:

„Nem tudni miért van az a jelenség, mely szerint a facebook-port néhány szóközt kidob a szövegből. nonbreakablespaces lenne benne, ami szűrődik? Ki tudja, meglehet. Ez a szöveg kezd olyan hosszúvá válni, amely talán megmutatja, hogy mi a baj.”

Átváltottam a szerkesztőt plain textre, a szöveg jól látszott. Beküldés után megnyitottam szerkesztésre, fullhtml tökéletesen mutatja. Plain textként azonban:

<p><span data-scayt_word="Nem" data-scaytid="94">Nem</span> <span data-scayt_word="tudni" data-scaytid="95">tudni</span> <span data-scayt_word="miért" data-scaytid="96">miért</span> van <span data-scayt_word="az" data-scaytid="97">az</span> a <span data-scayt_word="jelenség" data-scaytid="98">jelenség</span>, <span data-scayt_word="mely" data-scaytid="99">mely</span> <span data-scayt_word="szerint" data-scaytid="100">szerint</span> a <span data-scayt_word="facebook-port" data-scaytid="101">facebook-port</span> <span data-scayt_word="néhány" data-scaytid="102">néhány</span> <span data-scayt_word="szóközt" data-scaytid="103">szóközt</span> <span data-scayt_word="kidob" data-scaytid="104">kidob</span> a <span data-scayt_word="szövegből" data-scaytid="105">szövegből</span>. <span data-scayt_word="nonbreakablespaces" data-scaytid="106">nonbreakablespaces</span> <span data-scayt_word="lenne" data-scaytid="107">lenne</span> <span data-scayt_word="benne" data-scaytid="108">benne</span>, <span data-scayt_word="ami" data-scaytid="109">ami</span> <span data-scayt_word="szűrődik" data-scaytid="110">szűrődik</span>? <span data-scayt_word="Ki" data-scaytid="111">Ki</span> <span data-scayt_word="tudja" data-scaytid="112">tudja</span>, <span data-scayt_word="meglehet" data-scaytid="113">meglehet</span>. <span data-scayt_word="Ez" data-scaytid="114">Ez</span> a <span data-scayt_word="szöveg" data-scaytid="115">szöveg</span> <span data-scayt_word="kezd" data-scaytid="116">kezd</span> <span data-scayt_word="olyan" data-scaytid="117">olyan</span> <span data-scayt_word="hosszúvá" data-scaytid="118">hosszúvá</span> <span data-scayt_word="válni" data-scaytid="119">válni</span>, <span data-scayt_word="amely" data-scaytid="120">amely</span> <span data-scayt_word="talán" data-scaytid="121">talán</span> <span data-scayt_word="megmutatja" data-scaytid="122">megmutatja</span>, <span data-scayt_word="hogy" data-scaytid="123">hogy</span> mi a <span data-scayt_word="baj" data-scaytid="124">baj</span>.</p>

Itt néhány szót nem dolgoz fel valami (ckeditor??) és ott meg is marad a szóköz a facebook postban. Amit körbebástyáz span-nal, azon szavak körül a szóköz elvész.
Feltelepítek egy másik editort az oldalra, hátha...

0
0
Astutus képe

Sajnálom, most csinálom először (php, mysql, apache), eddig tárhely szolgáltatónál volt az oldalam, de bizonyos okok miatt saját gépre költöztettem és itt szeretném csinálni tovább. OpenSuSE-vel raktam fel mindent, a rewrite modult engedélyeztem az apache-ban és találtam valamilyen terminálos ellenőrzést is, arra is azt írta ki hogy engedélyezve van a rewrite_module.

Az adatok:
Op. rendszer: open SUSE 11.4
Apache: 2.2.17
phpMyAdmin: 3.3.10
Mysql: 5.0.7
Phpinfo:

System 	Linux Wolfsys 2.6.37.1-1.2-desktop #1 SMP PREEMPT 2011-02-21 10:34:10 +0100 x86_64
Server API 	Apache 2.0 Handler
Virtual Directory Support 	disabled
Configuration File (php.ini) Path 	/etc/php5/apache2
Loaded Configuration File 	/etc/php5/apache2/php.ini
Scan this dir for additional .ini files 	/etc/php5/conf.d
Additional .ini files parsed 	/etc/php5/conf.d/bz2.ini, /etc/php5/conf.d/ctype.ini, /etc/php5/conf.d/curl.ini, /etc/php5/conf.d/dba.ini, /etc/php5/conf.d/dom.ini, /etc/php5/conf.d/ftp.ini, /etc/php5/conf.d/gd.ini, /etc/php5/conf.d/hash.ini, /etc/php5/conf.d/iconv.ini, /etc/php5/conf.d/json.ini, /etc/php5/conf.d/mbstring.ini, /etc/php5/conf.d/mcrypt.ini, /etc/php5/conf.d/mysql.ini, /etc/php5/conf.d/mysqli.ini, /etc/php5/conf.d/openssl.ini, /etc/php5/conf.d/pdo.ini, /etc/php5/conf.d/pdo_mysql.ini, /etc/php5/conf.d/pdo_sqlite.ini, /etc/php5/conf.d/sqlite.ini, /etc/php5/conf.d/sqlite3.ini, /etc/php5/conf.d/tokenizer.ini, /etc/php5/conf.d/xmlwriter.ini, /etc/php5/conf.d/zip.ini, /etc/php5/conf.d/zlib.ini
PHP API 	20090626
PHP Extension 	20090626
Zend Extension 	220090626
Zend Extension Build 	API220090626,NTS
PHP Extension Build 	API20090626,NTS
Debug Build 	no
Thread Safety 	disabled
Zend Memory Manager 	enabled
Zend Multibyte Support 	disabled
IPv6 Support 	enabled
Registered PHP Streams 	php, file, glob, data, http, ftp, compress.bzip2, https, ftps, zip, compress.zlib
Registered Stream Socket Transports 	tcp, udp, unix, udg, ssl, sslv3, sslv2, tls
Registered Stream Filters 	string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, dechunk, bzip2.*, convert.iconv.*, mcrypt.*, mdecrypt.*, zlib.* 

Köszönöm!

0
0

Saját form készítése

Phoere képe

Sziasztok!

Úgy adódott, hogy el kellene készítenem egy saját formot. Elkészítettem hozzá a saját modult, de valamit nem sikerült jól összeraknom, mert a az eredmény oldalon hibaüzenetet kapok. Biztos valami tök egyszerű hiba van benne.
Az űrlap egyszerű (nyilván a végleges ennél bővebb lesz): két fieldset van, az elsőben egy textfield, a másodikban két checkbox.

Az űrlap rendben megjelenik, kitöltés után megnyílik kért eredményoldal.
Az eredményoldalon PHP-kódban van jelenleg a $result= function urlap_submit() utasítás.

Drupal verzió: 
black71 képe

REMOTE_ADDR -->

includes/bootstrap.inc
includes/common.inc
includes/session.inc
modules/comment/comment.module
modules/poll/poll.module
modules/statistics/statistics.module

HTTP_HOST -->

includes/bootstrap.inc
modules/statistics/statistics.module

csak halkan megjegyzem hiányolom a drupalbol hogy nem kepes lekezelni az ip -t es a host -ot.
ket fv. -t ha allandositanak nem lenne ilyen problema a szervereken.

function client_ip() {
	if (isset ($_SERVER['HTTP_X_FORWARDED_FOR'])){
		$ipaddr = $_SERVER['HTTP_X_FORWARDED_FOR'];
	} else {
		$ipaddr = $_SERVER['REMOTE_ADDR'];
	}
	return $ipaddr;
}
 
function host_ip() {
	if (isset ($_SERVER['HTTP_X_FORWARDED_HOST'])){
		$hostaddr = $_SERVER['HTTP_X_FORWARDED_HOST'];
	} else {
		$hostaddr = $_SERVER['HTTP_HOST'];
	}
	return $hostaddr;
}
0
0

Drupal 5.x, 7.x

Seemann képe

mert így logikusabbnak tűnik, de nem változott semmi.

<?php
  $view->filter = array (
    array (
      'tablename' => 'term_node_1',
      'field' => 'tid',
      'operator' => 'OR',
      'options' => '',
      'value' => array (
  0 => '2',
),
    ),
    array (
      'tablename' => 'node',
      'field' => 'distinct',
      'operator' => '=',
      'options' => '',
      'value' => array (
  0 => 'distinct',
),
    ),
  );
?>

Azt nem látom, a különböző szűrőket hogyan lehet összekapcsolni, illetve jól gondolom, hogy AND -el vannak kapcsolva? (Ami tulajdonképpen jó kellene hogy legyen most az én esetemben)

0
0

Seemann

alippai képe

Ezekkel nagy valószínűséggel semmire nem mész, mert a buddylist áprilisi??? verziójához készült, de azért:

function buddylisttab_menu($may_cache) {
  $items = array();
  if (!$may_cache) {
    $items[] = array('path' => 'user/'.arg(1).'/buddylist', 
                           'title' => t('buddies'),
                           'access' => TRUE, 
                           'callback'=> 'buddylist_buddylisting_page',
                           'callback arguments'=> array(arg(1)),
                           'type' => MENU_LOCAL_TASK, 
                           'weight' => 8
    );
  }
  return $items;
}

Nemtudom, hogy mennyire vagy jártas modulfejlesztésben, ill. hogy ez még működik e az aktuális verzióval (ez elméletileg egy tabot hoz létre a felhasználók profil oldalán)

buddylist_buddylisting_page függvényben tudod a html-t a kimenetnek átállítani (régebben így volt) - a többi smink már css kérdése

ha van valami konkrét kérdésed, kérdezz nyugodtan

bocs de nincs időm utánnanézni a dolgoknak, majd talán februárban

0
0

Lippai Ádám
young element