First semi-stable version
1292
soundmap/api/getid3.lib.php
Normal file
1757
soundmap/api/getid3.php
Normal file
2011
soundmap/api/module.audio.mp3.php
Normal file
372
soundmap/api/module.tag.apetag.php
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
|
// available at http://getid3.sourceforge.net //
|
||||||
|
// or http://www.getid3.org //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// See readme.txt for more details //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// module.tag.apetag.php //
|
||||||
|
// module for analyzing APE tags //
|
||||||
|
// dependencies: NONE //
|
||||||
|
// ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class getid3_apetag extends getid3_handler
|
||||||
|
{
|
||||||
|
var $inline_attachments = true; // true: return full data for all attachments; false: return no data for all attachments; integer: return data for attachments <= than this; string: save as file to this directory
|
||||||
|
var $overrideendoffset = 0;
|
||||||
|
|
||||||
|
function Analyze() {
|
||||||
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
if (!getid3_lib::intValueSupported($info['filesize'])) {
|
||||||
|
$info['warning'][] = 'Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$id3v1tagsize = 128;
|
||||||
|
$apetagheadersize = 32;
|
||||||
|
$lyrics3tagsize = 10;
|
||||||
|
|
||||||
|
if ($this->overrideendoffset == 0) {
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, 0 - $id3v1tagsize - $apetagheadersize - $lyrics3tagsize, SEEK_END);
|
||||||
|
$APEfooterID3v1 = fread($this->getid3->fp, $id3v1tagsize + $apetagheadersize + $lyrics3tagsize);
|
||||||
|
|
||||||
|
//if (preg_match('/APETAGEX.{24}TAG.{125}$/i', $APEfooterID3v1)) {
|
||||||
|
if (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $id3v1tagsize - $apetagheadersize, 8) == 'APETAGEX') {
|
||||||
|
|
||||||
|
// APE tag found before ID3v1
|
||||||
|
$info['ape']['tag_offset_end'] = $info['filesize'] - $id3v1tagsize;
|
||||||
|
|
||||||
|
//} elseif (preg_match('/APETAGEX.{24}$/i', $APEfooterID3v1)) {
|
||||||
|
} elseif (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $apetagheadersize, 8) == 'APETAGEX') {
|
||||||
|
|
||||||
|
// APE tag found, no ID3v1
|
||||||
|
$info['ape']['tag_offset_end'] = $info['filesize'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, $this->overrideendoffset - $apetagheadersize, SEEK_SET);
|
||||||
|
if (fread($this->getid3->fp, 8) == 'APETAGEX') {
|
||||||
|
$info['ape']['tag_offset_end'] = $this->overrideendoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!isset($info['ape']['tag_offset_end'])) {
|
||||||
|
|
||||||
|
// APE tag not found
|
||||||
|
unset($info['ape']);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// shortcut
|
||||||
|
$thisfile_ape = &$info['ape'];
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, $thisfile_ape['tag_offset_end'] - $apetagheadersize, SEEK_SET);
|
||||||
|
$APEfooterData = fread($this->getid3->fp, 32);
|
||||||
|
if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) {
|
||||||
|
$info['error'][] = 'Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end'];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) {
|
||||||
|
fseek($this->getid3->fp, $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'] - $apetagheadersize, SEEK_SET);
|
||||||
|
$thisfile_ape['tag_offset_start'] = ftell($this->getid3->fp);
|
||||||
|
$APEtagData = fread($this->getid3->fp, $thisfile_ape['footer']['raw']['tagsize'] + $apetagheadersize);
|
||||||
|
} else {
|
||||||
|
$thisfile_ape['tag_offset_start'] = $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'];
|
||||||
|
fseek($this->getid3->fp, $thisfile_ape['tag_offset_start'], SEEK_SET);
|
||||||
|
$APEtagData = fread($this->getid3->fp, $thisfile_ape['footer']['raw']['tagsize']);
|
||||||
|
}
|
||||||
|
$info['avdataend'] = $thisfile_ape['tag_offset_start'];
|
||||||
|
|
||||||
|
if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) {
|
||||||
|
$info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in APEtag data';
|
||||||
|
unset($info['id3v1']);
|
||||||
|
foreach ($info['warning'] as $key => $value) {
|
||||||
|
if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
|
||||||
|
unset($info['warning'][$key]);
|
||||||
|
sort($info['warning']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset = 0;
|
||||||
|
if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) {
|
||||||
|
if ($thisfile_ape['header'] = $this->parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize))) {
|
||||||
|
$offset += $apetagheadersize;
|
||||||
|
} else {
|
||||||
|
$info['error'][] = 'Error parsing APE header at offset '.$thisfile_ape['tag_offset_start'];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shortcut
|
||||||
|
$info['replay_gain'] = array();
|
||||||
|
$thisfile_replaygain = &$info['replay_gain'];
|
||||||
|
|
||||||
|
for ($i = 0; $i < $thisfile_ape['footer']['raw']['tag_items']; $i++) {
|
||||||
|
$value_size = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
$item_flags = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
|
||||||
|
$offset += 4;
|
||||||
|
if (strstr(substr($APEtagData, $offset), "\x00") === false) {
|
||||||
|
$info['error'][] = 'Cannot find null-byte (0x00) seperator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ItemKeyLength = strpos($APEtagData, "\x00", $offset) - $offset;
|
||||||
|
$item_key = strtolower(substr($APEtagData, $offset, $ItemKeyLength));
|
||||||
|
|
||||||
|
// shortcut
|
||||||
|
$thisfile_ape['items'][$item_key] = array();
|
||||||
|
$thisfile_ape_items_current = &$thisfile_ape['items'][$item_key];
|
||||||
|
|
||||||
|
$thisfile_ape_items_current['offset'] = $thisfile_ape['tag_offset_start'] + $offset;
|
||||||
|
|
||||||
|
$offset += ($ItemKeyLength + 1); // skip 0x00 terminator
|
||||||
|
$thisfile_ape_items_current['data'] = substr($APEtagData, $offset, $value_size);
|
||||||
|
$offset += $value_size;
|
||||||
|
|
||||||
|
$thisfile_ape_items_current['flags'] = $this->parseAPEtagFlags($item_flags);
|
||||||
|
switch ($thisfile_ape_items_current['flags']['item_contents_raw']) {
|
||||||
|
case 0: // UTF-8
|
||||||
|
case 3: // Locator (URL, filename, etc), UTF-8 encoded
|
||||||
|
$thisfile_ape_items_current['data'] = explode("\x00", trim($thisfile_ape_items_current['data']));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // binary data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (strtolower($item_key)) {
|
||||||
|
case 'replaygain_track_gain':
|
||||||
|
$thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
||||||
|
$thisfile_replaygain['track']['originator'] = 'unspecified';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'replaygain_track_peak':
|
||||||
|
$thisfile_replaygain['track']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
||||||
|
$thisfile_replaygain['track']['originator'] = 'unspecified';
|
||||||
|
if ($thisfile_replaygain['track']['peak'] <= 0) {
|
||||||
|
$info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'replaygain_album_gain':
|
||||||
|
$thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
||||||
|
$thisfile_replaygain['album']['originator'] = 'unspecified';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'replaygain_album_peak':
|
||||||
|
$thisfile_replaygain['album']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
|
||||||
|
$thisfile_replaygain['album']['originator'] = 'unspecified';
|
||||||
|
if ($thisfile_replaygain['album']['peak'] <= 0) {
|
||||||
|
$info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'mp3gain_undo':
|
||||||
|
list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $thisfile_ape_items_current['data'][0]);
|
||||||
|
$thisfile_replaygain['mp3gain']['undo_left'] = intval($mp3gain_undo_left);
|
||||||
|
$thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
|
||||||
|
$thisfile_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'mp3gain_minmax':
|
||||||
|
list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $thisfile_ape_items_current['data'][0]);
|
||||||
|
$thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
|
||||||
|
$thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'mp3gain_album_minmax':
|
||||||
|
list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $thisfile_ape_items_current['data'][0]);
|
||||||
|
$thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
|
||||||
|
$thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'tracknumber':
|
||||||
|
if (is_array($thisfile_ape_items_current['data'])) {
|
||||||
|
foreach ($thisfile_ape_items_current['data'] as $comment) {
|
||||||
|
$thisfile_ape['comments']['track'][] = $comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'cover art (artist)':
|
||||||
|
case 'cover art (back)':
|
||||||
|
case 'cover art (band logo)':
|
||||||
|
case 'cover art (band)':
|
||||||
|
case 'cover art (colored fish)':
|
||||||
|
case 'cover art (composer)':
|
||||||
|
case 'cover art (conductor)':
|
||||||
|
case 'cover art (front)':
|
||||||
|
case 'cover art (icon)':
|
||||||
|
case 'cover art (illustration)':
|
||||||
|
case 'cover art (lead)':
|
||||||
|
case 'cover art (leaflet)':
|
||||||
|
case 'cover art (lyricist)':
|
||||||
|
case 'cover art (media)':
|
||||||
|
case 'cover art (movie scene)':
|
||||||
|
case 'cover art (other icon)':
|
||||||
|
case 'cover art (other)':
|
||||||
|
case 'cover art (performance)':
|
||||||
|
case 'cover art (publisher logo)':
|
||||||
|
case 'cover art (recording)':
|
||||||
|
case 'cover art (studio)':
|
||||||
|
// list of possible cover arts from http://taglib-sharp.sourcearchive.com/documentation/2.0.3.0-2/Ape_2Tag_8cs-source.html
|
||||||
|
list($thisfile_ape_items_current['filename'], $thisfile_ape_items_current['data']) = explode("\x00", $thisfile_ape_items_current['data'], 2);
|
||||||
|
$thisfile_ape_items_current['data_offset'] = $thisfile_ape_items_current['offset'] + strlen($thisfile_ape_items_current['filename']."\x00");
|
||||||
|
$thisfile_ape_items_current['data_length'] = strlen($thisfile_ape_items_current['data']);
|
||||||
|
|
||||||
|
$thisfile_ape_items_current['image_mime'] = '';
|
||||||
|
$imageinfo = array();
|
||||||
|
$imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
|
||||||
|
$thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ($this->inline_attachments === false) {
|
||||||
|
// skip entirely
|
||||||
|
unset($thisfile_ape_items_current['data']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($this->inline_attachments === true) {
|
||||||
|
// great
|
||||||
|
} elseif (is_int($this->inline_attachments)) {
|
||||||
|
if ($this->inline_attachments < $thisfile_ape_items_current['data_length']) {
|
||||||
|
// too big, skip
|
||||||
|
$info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)';
|
||||||
|
unset($thisfile_ape_items_current['data']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} elseif (is_string($this->inline_attachments)) {
|
||||||
|
$this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR);
|
||||||
|
if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) {
|
||||||
|
// cannot write, skip
|
||||||
|
$info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)';
|
||||||
|
unset($thisfile_ape_items_current['data']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if we get this far, must be OK
|
||||||
|
if (is_string($this->inline_attachments)) {
|
||||||
|
$destination_filename = $this->inline_attachments.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$thisfile_ape_items_current['data_offset'];
|
||||||
|
if (!file_exists($destination_filename) || is_writable($destination_filename)) {
|
||||||
|
file_put_contents($destination_filename, $thisfile_ape_items_current['data']);
|
||||||
|
} else {
|
||||||
|
$info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)';
|
||||||
|
}
|
||||||
|
$thisfile_ape_items_current['data_filename'] = $destination_filename;
|
||||||
|
unset($thisfile_ape_items_current['data']);
|
||||||
|
} else {
|
||||||
|
if (!isset($info['ape']['comments']['picture'])) {
|
||||||
|
$info['ape']['comments']['picture'] = array();
|
||||||
|
}
|
||||||
|
$info['ape']['comments']['picture'][] = array('data'=>$thisfile_ape_items_current['data'], 'image_mime'=>$thisfile_ape_items_current['image_mime']);
|
||||||
|
}
|
||||||
|
} while (false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (is_array($thisfile_ape_items_current['data'])) {
|
||||||
|
foreach ($thisfile_ape_items_current['data'] as $comment) {
|
||||||
|
$thisfile_ape['comments'][strtolower($item_key)][] = $comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (empty($thisfile_replaygain)) {
|
||||||
|
unset($info['replay_gain']);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAPEheaderFooter($APEheaderFooterData) {
|
||||||
|
// http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html
|
||||||
|
|
||||||
|
// shortcut
|
||||||
|
$headerfooterinfo['raw'] = array();
|
||||||
|
$headerfooterinfo_raw = &$headerfooterinfo['raw'];
|
||||||
|
|
||||||
|
$headerfooterinfo_raw['footer_tag'] = substr($APEheaderFooterData, 0, 8);
|
||||||
|
if ($headerfooterinfo_raw['footer_tag'] != 'APETAGEX') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$headerfooterinfo_raw['version'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 8, 4));
|
||||||
|
$headerfooterinfo_raw['tagsize'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 12, 4));
|
||||||
|
$headerfooterinfo_raw['tag_items'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 16, 4));
|
||||||
|
$headerfooterinfo_raw['global_flags'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 20, 4));
|
||||||
|
$headerfooterinfo_raw['reserved'] = substr($APEheaderFooterData, 24, 8);
|
||||||
|
|
||||||
|
$headerfooterinfo['tag_version'] = $headerfooterinfo_raw['version'] / 1000;
|
||||||
|
if ($headerfooterinfo['tag_version'] >= 2) {
|
||||||
|
$headerfooterinfo['flags'] = $this->parseAPEtagFlags($headerfooterinfo_raw['global_flags']);
|
||||||
|
}
|
||||||
|
return $headerfooterinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAPEtagFlags($rawflagint) {
|
||||||
|
// "Note: APE Tags 1.0 do not use any of the APE Tag flags.
|
||||||
|
// All are set to zero on creation and ignored on reading."
|
||||||
|
// http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html
|
||||||
|
$flags['header'] = (bool) ($rawflagint & 0x80000000);
|
||||||
|
$flags['footer'] = (bool) ($rawflagint & 0x40000000);
|
||||||
|
$flags['this_is_header'] = (bool) ($rawflagint & 0x20000000);
|
||||||
|
$flags['item_contents_raw'] = ($rawflagint & 0x00000006) >> 1;
|
||||||
|
$flags['read_only'] = (bool) ($rawflagint & 0x00000001);
|
||||||
|
|
||||||
|
$flags['item_contents'] = $this->APEcontentTypeFlagLookup($flags['item_contents_raw']);
|
||||||
|
|
||||||
|
return $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
function APEcontentTypeFlagLookup($contenttypeid) {
|
||||||
|
static $APEcontentTypeFlagLookup = array(
|
||||||
|
0 => 'utf-8',
|
||||||
|
1 => 'binary',
|
||||||
|
2 => 'external',
|
||||||
|
3 => 'reserved'
|
||||||
|
);
|
||||||
|
return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
function APEtagItemIsUTF8Lookup($itemkey) {
|
||||||
|
static $APEtagItemIsUTF8Lookup = array(
|
||||||
|
'title',
|
||||||
|
'subtitle',
|
||||||
|
'artist',
|
||||||
|
'album',
|
||||||
|
'debut album',
|
||||||
|
'publisher',
|
||||||
|
'conductor',
|
||||||
|
'track',
|
||||||
|
'composer',
|
||||||
|
'comment',
|
||||||
|
'copyright',
|
||||||
|
'publicationright',
|
||||||
|
'file',
|
||||||
|
'year',
|
||||||
|
'record date',
|
||||||
|
'record location',
|
||||||
|
'genre',
|
||||||
|
'media',
|
||||||
|
'related',
|
||||||
|
'isrc',
|
||||||
|
'abstract',
|
||||||
|
'language',
|
||||||
|
'bibliography'
|
||||||
|
);
|
||||||
|
return in_array(strtolower($itemkey), $APEtagItemIsUTF8Lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
362
soundmap/api/module.tag.id3v1.php
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
|
// available at http://getid3.sourceforge.net //
|
||||||
|
// or http://www.getid3.org //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// See readme.txt for more details //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// module.tag.id3v1.php //
|
||||||
|
// module for analyzing ID3v1 tags //
|
||||||
|
// dependencies: NONE //
|
||||||
|
// ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
class getid3_id3v1 extends getid3_handler
|
||||||
|
{
|
||||||
|
|
||||||
|
function Analyze() {
|
||||||
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
if (!getid3_lib::intValueSupported($info['filesize'])) {
|
||||||
|
$info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, -256, SEEK_END);
|
||||||
|
$preid3v1 = fread($this->getid3->fp, 128);
|
||||||
|
$id3v1tag = fread($this->getid3->fp, 128);
|
||||||
|
|
||||||
|
if (substr($id3v1tag, 0, 3) == 'TAG') {
|
||||||
|
|
||||||
|
$info['avdataend'] = $info['filesize'] - 128;
|
||||||
|
|
||||||
|
$ParsedID3v1['title'] = $this->cutfield(substr($id3v1tag, 3, 30));
|
||||||
|
$ParsedID3v1['artist'] = $this->cutfield(substr($id3v1tag, 33, 30));
|
||||||
|
$ParsedID3v1['album'] = $this->cutfield(substr($id3v1tag, 63, 30));
|
||||||
|
$ParsedID3v1['year'] = $this->cutfield(substr($id3v1tag, 93, 4));
|
||||||
|
$ParsedID3v1['comment'] = substr($id3v1tag, 97, 30); // can't remove nulls yet, track detection depends on them
|
||||||
|
$ParsedID3v1['genreid'] = ord(substr($id3v1tag, 127, 1));
|
||||||
|
|
||||||
|
// If second-last byte of comment field is null and last byte of comment field is non-null
|
||||||
|
// then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
|
||||||
|
if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
|
||||||
|
$ParsedID3v1['track'] = ord(substr($ParsedID3v1['comment'], 29, 1));
|
||||||
|
$ParsedID3v1['comment'] = substr($ParsedID3v1['comment'], 0, 28);
|
||||||
|
}
|
||||||
|
$ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
|
||||||
|
|
||||||
|
$ParsedID3v1['genre'] = $this->LookupGenreName($ParsedID3v1['genreid']);
|
||||||
|
if (!empty($ParsedID3v1['genre'])) {
|
||||||
|
unset($ParsedID3v1['genreid']);
|
||||||
|
}
|
||||||
|
if (isset($ParsedID3v1['genre']) && (empty($ParsedID3v1['genre']) || ($ParsedID3v1['genre'] == 'Unknown'))) {
|
||||||
|
unset($ParsedID3v1['genre']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($ParsedID3v1 as $key => $value) {
|
||||||
|
$ParsedID3v1['comments'][$key][0] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
|
||||||
|
$GoodFormatID3v1tag = $this->GenerateID3v1Tag(
|
||||||
|
$ParsedID3v1['title'],
|
||||||
|
$ParsedID3v1['artist'],
|
||||||
|
$ParsedID3v1['album'],
|
||||||
|
$ParsedID3v1['year'],
|
||||||
|
(isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
|
||||||
|
$ParsedID3v1['comment'],
|
||||||
|
(!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
|
||||||
|
$ParsedID3v1['padding_valid'] = true;
|
||||||
|
if ($id3v1tag !== $GoodFormatID3v1tag) {
|
||||||
|
$ParsedID3v1['padding_valid'] = false;
|
||||||
|
$info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ParsedID3v1['tag_offset_end'] = $info['filesize'];
|
||||||
|
$ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128;
|
||||||
|
|
||||||
|
$info['id3v1'] = $ParsedID3v1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (substr($preid3v1, 0, 3) == 'TAG') {
|
||||||
|
// The way iTunes handles tags is, well, brain-damaged.
|
||||||
|
// It completely ignores v1 if ID3v2 is present.
|
||||||
|
// This goes as far as adding a new v1 tag *even if there already is one*
|
||||||
|
|
||||||
|
// A suspected double-ID3v1 tag has been detected, but it could be that
|
||||||
|
// the "TAG" identifier is a legitimate part of an APE or Lyrics3 tag
|
||||||
|
if (substr($preid3v1, 96, 8) == 'APETAGEX') {
|
||||||
|
// an APE tag footer was found before the last ID3v1, assume false "TAG" synch
|
||||||
|
} elseif (substr($preid3v1, 119, 6) == 'LYRICS') {
|
||||||
|
// a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch
|
||||||
|
} else {
|
||||||
|
// APE and Lyrics3 footers not found - assume double ID3v1
|
||||||
|
$info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes';
|
||||||
|
$info['avdataend'] -= 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function cutfield($str) {
|
||||||
|
return trim(substr($str, 0, strcspn($str, "\x00")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static function ArrayOfGenres($allowSCMPXextended=false) {
|
||||||
|
static $GenreLookup = array(
|
||||||
|
0 => 'Blues',
|
||||||
|
1 => 'Classic Rock',
|
||||||
|
2 => 'Country',
|
||||||
|
3 => 'Dance',
|
||||||
|
4 => 'Disco',
|
||||||
|
5 => 'Funk',
|
||||||
|
6 => 'Grunge',
|
||||||
|
7 => 'Hip-Hop',
|
||||||
|
8 => 'Jazz',
|
||||||
|
9 => 'Metal',
|
||||||
|
10 => 'New Age',
|
||||||
|
11 => 'Oldies',
|
||||||
|
12 => 'Other',
|
||||||
|
13 => 'Pop',
|
||||||
|
14 => 'R&B',
|
||||||
|
15 => 'Rap',
|
||||||
|
16 => 'Reggae',
|
||||||
|
17 => 'Rock',
|
||||||
|
18 => 'Techno',
|
||||||
|
19 => 'Industrial',
|
||||||
|
20 => 'Alternative',
|
||||||
|
21 => 'Ska',
|
||||||
|
22 => 'Death Metal',
|
||||||
|
23 => 'Pranks',
|
||||||
|
24 => 'Soundtrack',
|
||||||
|
25 => 'Euro-Techno',
|
||||||
|
26 => 'Ambient',
|
||||||
|
27 => 'Trip-Hop',
|
||||||
|
28 => 'Vocal',
|
||||||
|
29 => 'Jazz+Funk',
|
||||||
|
30 => 'Fusion',
|
||||||
|
31 => 'Trance',
|
||||||
|
32 => 'Classical',
|
||||||
|
33 => 'Instrumental',
|
||||||
|
34 => 'Acid',
|
||||||
|
35 => 'House',
|
||||||
|
36 => 'Game',
|
||||||
|
37 => 'Sound Clip',
|
||||||
|
38 => 'Gospel',
|
||||||
|
39 => 'Noise',
|
||||||
|
40 => 'Alt. Rock',
|
||||||
|
41 => 'Bass',
|
||||||
|
42 => 'Soul',
|
||||||
|
43 => 'Punk',
|
||||||
|
44 => 'Space',
|
||||||
|
45 => 'Meditative',
|
||||||
|
46 => 'Instrumental Pop',
|
||||||
|
47 => 'Instrumental Rock',
|
||||||
|
48 => 'Ethnic',
|
||||||
|
49 => 'Gothic',
|
||||||
|
50 => 'Darkwave',
|
||||||
|
51 => 'Techno-Industrial',
|
||||||
|
52 => 'Electronic',
|
||||||
|
53 => 'Pop-Folk',
|
||||||
|
54 => 'Eurodance',
|
||||||
|
55 => 'Dream',
|
||||||
|
56 => 'Southern Rock',
|
||||||
|
57 => 'Comedy',
|
||||||
|
58 => 'Cult',
|
||||||
|
59 => 'Gangsta Rap',
|
||||||
|
60 => 'Top 40',
|
||||||
|
61 => 'Christian Rap',
|
||||||
|
62 => 'Pop/Funk',
|
||||||
|
63 => 'Jungle',
|
||||||
|
64 => 'Native American',
|
||||||
|
65 => 'Cabaret',
|
||||||
|
66 => 'New Wave',
|
||||||
|
67 => 'Psychedelic',
|
||||||
|
68 => 'Rave',
|
||||||
|
69 => 'Showtunes',
|
||||||
|
70 => 'Trailer',
|
||||||
|
71 => 'Lo-Fi',
|
||||||
|
72 => 'Tribal',
|
||||||
|
73 => 'Acid Punk',
|
||||||
|
74 => 'Acid Jazz',
|
||||||
|
75 => 'Polka',
|
||||||
|
76 => 'Retro',
|
||||||
|
77 => 'Musical',
|
||||||
|
78 => 'Rock & Roll',
|
||||||
|
79 => 'Hard Rock',
|
||||||
|
80 => 'Folk',
|
||||||
|
81 => 'Folk/Rock',
|
||||||
|
82 => 'National Folk',
|
||||||
|
83 => 'Swing',
|
||||||
|
84 => 'Fast-Fusion',
|
||||||
|
85 => 'Bebob',
|
||||||
|
86 => 'Latin',
|
||||||
|
87 => 'Revival',
|
||||||
|
88 => 'Celtic',
|
||||||
|
89 => 'Bluegrass',
|
||||||
|
90 => 'Avantgarde',
|
||||||
|
91 => 'Gothic Rock',
|
||||||
|
92 => 'Progressive Rock',
|
||||||
|
93 => 'Psychedelic Rock',
|
||||||
|
94 => 'Symphonic Rock',
|
||||||
|
95 => 'Slow Rock',
|
||||||
|
96 => 'Big Band',
|
||||||
|
97 => 'Chorus',
|
||||||
|
98 => 'Easy Listening',
|
||||||
|
99 => 'Acoustic',
|
||||||
|
100 => 'Humour',
|
||||||
|
101 => 'Speech',
|
||||||
|
102 => 'Chanson',
|
||||||
|
103 => 'Opera',
|
||||||
|
104 => 'Chamber Music',
|
||||||
|
105 => 'Sonata',
|
||||||
|
106 => 'Symphony',
|
||||||
|
107 => 'Booty Bass',
|
||||||
|
108 => 'Primus',
|
||||||
|
109 => 'Porn Groove',
|
||||||
|
110 => 'Satire',
|
||||||
|
111 => 'Slow Jam',
|
||||||
|
112 => 'Club',
|
||||||
|
113 => 'Tango',
|
||||||
|
114 => 'Samba',
|
||||||
|
115 => 'Folklore',
|
||||||
|
116 => 'Ballad',
|
||||||
|
117 => 'Power Ballad',
|
||||||
|
118 => 'Rhythmic Soul',
|
||||||
|
119 => 'Freestyle',
|
||||||
|
120 => 'Duet',
|
||||||
|
121 => 'Punk Rock',
|
||||||
|
122 => 'Drum Solo',
|
||||||
|
123 => 'A Cappella',
|
||||||
|
124 => 'Euro-House',
|
||||||
|
125 => 'Dance Hall',
|
||||||
|
126 => 'Goa',
|
||||||
|
127 => 'Drum & Bass',
|
||||||
|
128 => 'Club-House',
|
||||||
|
129 => 'Hardcore',
|
||||||
|
130 => 'Terror',
|
||||||
|
131 => 'Indie',
|
||||||
|
132 => 'BritPop',
|
||||||
|
133 => 'Negerpunk',
|
||||||
|
134 => 'Polsk Punk',
|
||||||
|
135 => 'Beat',
|
||||||
|
136 => 'Christian Gangsta Rap',
|
||||||
|
137 => 'Heavy Metal',
|
||||||
|
138 => 'Black Metal',
|
||||||
|
139 => 'Crossover',
|
||||||
|
140 => 'Contemporary Christian',
|
||||||
|
141 => 'Christian Rock',
|
||||||
|
142 => 'Merengue',
|
||||||
|
143 => 'Salsa',
|
||||||
|
144 => 'Trash Metal',
|
||||||
|
145 => 'Anime',
|
||||||
|
146 => 'JPop',
|
||||||
|
147 => 'Synthpop',
|
||||||
|
|
||||||
|
255 => 'Unknown',
|
||||||
|
|
||||||
|
'CR' => 'Cover',
|
||||||
|
'RX' => 'Remix'
|
||||||
|
);
|
||||||
|
|
||||||
|
static $GenreLookupSCMPX = array();
|
||||||
|
if ($allowSCMPXextended && empty($GenreLookupSCMPX)) {
|
||||||
|
$GenreLookupSCMPX = $GenreLookup;
|
||||||
|
// http://www.geocities.co.jp/SiliconValley-Oakland/3664/alittle.html#GenreExtended
|
||||||
|
// Extended ID3v1 genres invented by SCMPX
|
||||||
|
// Note that 255 "Japanese Anime" conflicts with standard "Unknown"
|
||||||
|
$GenreLookupSCMPX[240] = 'Sacred';
|
||||||
|
$GenreLookupSCMPX[241] = 'Northern Europe';
|
||||||
|
$GenreLookupSCMPX[242] = 'Irish & Scottish';
|
||||||
|
$GenreLookupSCMPX[243] = 'Scotland';
|
||||||
|
$GenreLookupSCMPX[244] = 'Ethnic Europe';
|
||||||
|
$GenreLookupSCMPX[245] = 'Enka';
|
||||||
|
$GenreLookupSCMPX[246] = 'Children\'s Song';
|
||||||
|
$GenreLookupSCMPX[247] = 'Japanese Sky';
|
||||||
|
$GenreLookupSCMPX[248] = 'Japanese Heavy Rock';
|
||||||
|
$GenreLookupSCMPX[249] = 'Japanese Doom Rock';
|
||||||
|
$GenreLookupSCMPX[250] = 'Japanese J-POP';
|
||||||
|
$GenreLookupSCMPX[251] = 'Japanese Seiyu';
|
||||||
|
$GenreLookupSCMPX[252] = 'Japanese Ambient Techno';
|
||||||
|
$GenreLookupSCMPX[253] = 'Japanese Moemoe';
|
||||||
|
$GenreLookupSCMPX[254] = 'Japanese Tokusatsu';
|
||||||
|
//$GenreLookupSCMPX[255] = 'Japanese Anime';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function LookupGenreName($genreid, $allowSCMPXextended=true) {
|
||||||
|
switch ($genreid) {
|
||||||
|
case 'RX':
|
||||||
|
case 'CR':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!is_numeric($genreid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$genreid = intval($genreid); // to handle 3 or '3' or '03'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$GenreLookup = getid3_id3v1::ArrayOfGenres($allowSCMPXextended);
|
||||||
|
return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function LookupGenreID($genre, $allowSCMPXextended=false) {
|
||||||
|
$GenreLookup = getid3_id3v1::ArrayOfGenres($allowSCMPXextended);
|
||||||
|
$LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
|
||||||
|
foreach ($GenreLookup as $key => $value) {
|
||||||
|
if (strtolower(str_replace(' ', '', $value)) == $LowerCaseNoSpaceSearchTerm) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function StandardiseID3v1GenreName($OriginalGenre) {
|
||||||
|
if (($GenreID = getid3_id3v1::LookupGenreID($OriginalGenre)) !== false) {
|
||||||
|
return getid3_id3v1::LookupGenreName($GenreID);
|
||||||
|
}
|
||||||
|
return $OriginalGenre;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
|
||||||
|
$ID3v1Tag = 'TAG';
|
||||||
|
$ID3v1Tag .= str_pad(trim(substr($title, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
|
||||||
|
$ID3v1Tag .= str_pad(trim(substr($artist, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
|
||||||
|
$ID3v1Tag .= str_pad(trim(substr($album, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
|
||||||
|
$ID3v1Tag .= str_pad(trim(substr($year, 0, 4)), 4, "\x00", STR_PAD_LEFT);
|
||||||
|
if (!empty($track) && ($track > 0) && ($track <= 255)) {
|
||||||
|
$ID3v1Tag .= str_pad(trim(substr($comment, 0, 28)), 28, "\x00", STR_PAD_RIGHT);
|
||||||
|
$ID3v1Tag .= "\x00";
|
||||||
|
if (gettype($track) == 'string') {
|
||||||
|
$track = (int) $track;
|
||||||
|
}
|
||||||
|
$ID3v1Tag .= chr($track);
|
||||||
|
} else {
|
||||||
|
$ID3v1Tag .= str_pad(trim(substr($comment, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
|
||||||
|
}
|
||||||
|
if (($genreid < 0) || ($genreid > 147)) {
|
||||||
|
$genreid = 255; // 'unknown' genre
|
||||||
|
}
|
||||||
|
switch (gettype($genreid)) {
|
||||||
|
case 'string':
|
||||||
|
case 'integer':
|
||||||
|
$ID3v1Tag .= chr(intval($genreid));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$ID3v1Tag .= chr(255); // 'unknown' genre
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ID3v1Tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
3303
soundmap/api/module.tag.id3v2.php
Normal file
297
soundmap/api/module.tag.lyrics3.php
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
|
// available at http://getid3.sourceforge.net //
|
||||||
|
// or http://www.getid3.org //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// See readme.txt for more details //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// //
|
||||||
|
// module.tag.lyrics3.php //
|
||||||
|
// module for analyzing Lyrics3 tags //
|
||||||
|
// dependencies: module.tag.apetag.php (optional) //
|
||||||
|
// ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
class getid3_lyrics3 extends getid3_handler
|
||||||
|
{
|
||||||
|
|
||||||
|
function Analyze() {
|
||||||
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
// http://www.volweb.cz/str/tags.htm
|
||||||
|
|
||||||
|
if (!getid3_lib::intValueSupported($info['filesize'])) {
|
||||||
|
$info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, (0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size]
|
||||||
|
$lyrics3_id3v1 = fread($this->getid3->fp, 128 + 9 + 6);
|
||||||
|
$lyrics3lsz = substr($lyrics3_id3v1, 0, 6); // Lyrics3size
|
||||||
|
$lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200
|
||||||
|
$id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1
|
||||||
|
|
||||||
|
if ($lyrics3end == 'LYRICSEND') {
|
||||||
|
// Lyrics3v1, ID3v1, no APE
|
||||||
|
|
||||||
|
$lyrics3size = 5100;
|
||||||
|
$lyrics3offset = $info['filesize'] - 128 - $lyrics3size;
|
||||||
|
$lyrics3version = 1;
|
||||||
|
|
||||||
|
} elseif ($lyrics3end == 'LYRICS200') {
|
||||||
|
// Lyrics3v2, ID3v1, no APE
|
||||||
|
|
||||||
|
// LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
|
||||||
|
$lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200');
|
||||||
|
$lyrics3offset = $info['filesize'] - 128 - $lyrics3size;
|
||||||
|
$lyrics3version = 2;
|
||||||
|
|
||||||
|
} elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICSEND')) {
|
||||||
|
// Lyrics3v1, no ID3v1, no APE
|
||||||
|
|
||||||
|
$lyrics3size = 5100;
|
||||||
|
$lyrics3offset = $info['filesize'] - $lyrics3size;
|
||||||
|
$lyrics3version = 1;
|
||||||
|
$lyrics3offset = $info['filesize'] - $lyrics3size;
|
||||||
|
|
||||||
|
} elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICS200')) {
|
||||||
|
|
||||||
|
// Lyrics3v2, no ID3v1, no APE
|
||||||
|
|
||||||
|
$lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
|
||||||
|
$lyrics3offset = $info['filesize'] - $lyrics3size;
|
||||||
|
$lyrics3version = 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (isset($info['ape']['tag_offset_start']) && ($info['ape']['tag_offset_start'] > 15)) {
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, $info['ape']['tag_offset_start'] - 15, SEEK_SET);
|
||||||
|
$lyrics3lsz = fread($this->getid3->fp, 6);
|
||||||
|
$lyrics3end = fread($this->getid3->fp, 9);
|
||||||
|
|
||||||
|
if ($lyrics3end == 'LYRICSEND') {
|
||||||
|
// Lyrics3v1, APE, maybe ID3v1
|
||||||
|
|
||||||
|
$lyrics3size = 5100;
|
||||||
|
$lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
|
||||||
|
$info['avdataend'] = $lyrics3offset;
|
||||||
|
$lyrics3version = 1;
|
||||||
|
$info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
|
||||||
|
|
||||||
|
} elseif ($lyrics3end == 'LYRICS200') {
|
||||||
|
// Lyrics3v2, APE, maybe ID3v1
|
||||||
|
|
||||||
|
$lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
|
||||||
|
$lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
|
||||||
|
$lyrics3version = 2;
|
||||||
|
$info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($lyrics3offset)) {
|
||||||
|
$info['avdataend'] = $lyrics3offset;
|
||||||
|
$this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size);
|
||||||
|
|
||||||
|
if (!isset($info['ape'])) {
|
||||||
|
$GETID3_ERRORARRAY = &$info['warning'];
|
||||||
|
if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, false)) {
|
||||||
|
$getid3_temp = new getID3();
|
||||||
|
$getid3_temp->openfile($this->getid3->filename);
|
||||||
|
$getid3_apetag = new getid3_apetag($getid3_temp);
|
||||||
|
$getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start'];
|
||||||
|
$getid3_apetag->Analyze();
|
||||||
|
if (!empty($getid3_temp->info['ape'])) {
|
||||||
|
$info['ape'] = $getid3_temp->info['ape'];
|
||||||
|
}
|
||||||
|
if (!empty($getid3_temp->info['replay_gain'])) {
|
||||||
|
$info['replay_gain'] = $getid3_temp->info['replay_gain'];
|
||||||
|
}
|
||||||
|
unset($getid3_temp, $getid3_apetag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLyrics3Data($endoffset, $version, $length) {
|
||||||
|
// http://www.volweb.cz/str/tags.htm
|
||||||
|
|
||||||
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
if (!getid3_lib::intValueSupported($endoffset)) {
|
||||||
|
$info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($this->getid3->fp, $endoffset, SEEK_SET);
|
||||||
|
if ($length <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$rawdata = fread($this->getid3->fp, $length);
|
||||||
|
|
||||||
|
$ParsedLyrics3['raw']['lyrics3version'] = $version;
|
||||||
|
$ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
|
||||||
|
$ParsedLyrics3['tag_offset_start'] = $endoffset;
|
||||||
|
$ParsedLyrics3['tag_offset_end'] = $endoffset + $length - 1;
|
||||||
|
|
||||||
|
if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') {
|
||||||
|
if (strpos($rawdata, 'LYRICSBEGIN') !== false) {
|
||||||
|
|
||||||
|
$info['warning'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version;
|
||||||
|
$info['avdataend'] = $endoffset + strpos($rawdata, 'LYRICSBEGIN');
|
||||||
|
$rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN'));
|
||||||
|
$length = strlen($rawdata);
|
||||||
|
$ParsedLyrics3['tag_offset_start'] = $info['avdataend'];
|
||||||
|
$ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$info['error'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead';
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($version) {
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICSEND') {
|
||||||
|
$ParsedLyrics3['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9));
|
||||||
|
$this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
|
||||||
|
} else {
|
||||||
|
$info['error'][] = '"LYRICSEND" expected at '.(ftell($this->getid3->fp) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICS200') {
|
||||||
|
$ParsedLyrics3['raw']['unparsed'] = substr($rawdata, 11, strlen($rawdata) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ
|
||||||
|
$rawdata = $ParsedLyrics3['raw']['unparsed'];
|
||||||
|
while (strlen($rawdata) > 0) {
|
||||||
|
$fieldname = substr($rawdata, 0, 3);
|
||||||
|
$fieldsize = (int) substr($rawdata, 3, 5);
|
||||||
|
$ParsedLyrics3['raw'][$fieldname] = substr($rawdata, 8, $fieldsize);
|
||||||
|
$rawdata = substr($rawdata, 3 + 5 + $fieldsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ParsedLyrics3['raw']['IND'])) {
|
||||||
|
$i = 0;
|
||||||
|
$flagnames = array('lyrics', 'timestamps', 'inhibitrandom');
|
||||||
|
foreach ($flagnames as $flagname) {
|
||||||
|
if (strlen($ParsedLyrics3['raw']['IND']) > $i++) {
|
||||||
|
$ParsedLyrics3['flags'][$flagname] = $this->IntString2Bool(substr($ParsedLyrics3['raw']['IND'], $i, 1 - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$fieldnametranslation = array('ETT'=>'title', 'EAR'=>'artist', 'EAL'=>'album', 'INF'=>'comment', 'AUT'=>'author');
|
||||||
|
foreach ($fieldnametranslation as $key => $value) {
|
||||||
|
if (isset($ParsedLyrics3['raw'][$key])) {
|
||||||
|
$ParsedLyrics3['comments'][$value][] = trim($ParsedLyrics3['raw'][$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($ParsedLyrics3['raw']['IMG'])) {
|
||||||
|
$imagestrings = explode("\r\n", $ParsedLyrics3['raw']['IMG']);
|
||||||
|
foreach ($imagestrings as $key => $imagestring) {
|
||||||
|
if (strpos($imagestring, '||') !== false) {
|
||||||
|
$imagearray = explode('||', $imagestring);
|
||||||
|
$ParsedLyrics3['images'][$key]['filename'] = (isset($imagearray[0]) ? $imagearray[0] : '');
|
||||||
|
$ParsedLyrics3['images'][$key]['description'] = (isset($imagearray[1]) ? $imagearray[1] : '');
|
||||||
|
$ParsedLyrics3['images'][$key]['timestamp'] = $this->Lyrics3Timestamp2Seconds(isset($imagearray[2]) ? $imagearray[2] : '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($ParsedLyrics3['raw']['LYR'])) {
|
||||||
|
$this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$info['error'][] = '"LYRICS200" expected at '.(ftell($this->getid3->fp) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$info['error'][] = 'Cannot process Lyrics3 version '.$version.' (only v1 and v2)';
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] <= $ParsedLyrics3['tag_offset_end'])) {
|
||||||
|
$info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data';
|
||||||
|
unset($info['id3v1']);
|
||||||
|
foreach ($info['warning'] as $key => $value) {
|
||||||
|
if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
|
||||||
|
unset($info['warning'][$key]);
|
||||||
|
sort($info['warning']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$info['lyrics3'] = $ParsedLyrics3;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Lyrics3Timestamp2Seconds($rawtimestamp) {
|
||||||
|
if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) {
|
||||||
|
return (int) (($regs[1] * 60) + $regs[2]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Lyrics3LyricsTimestampParse(&$Lyrics3data) {
|
||||||
|
$lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']);
|
||||||
|
foreach ($lyricsarray as $key => $lyricline) {
|
||||||
|
$regs = array();
|
||||||
|
unset($thislinetimestamps);
|
||||||
|
while (preg_match('#^(\\[[0-9]{2}:[0-9]{2}\\])#', $lyricline, $regs)) {
|
||||||
|
$thislinetimestamps[] = $this->Lyrics3Timestamp2Seconds($regs[0]);
|
||||||
|
$lyricline = str_replace($regs[0], '', $lyricline);
|
||||||
|
}
|
||||||
|
$notimestamplyricsarray[$key] = $lyricline;
|
||||||
|
if (isset($thislinetimestamps) && is_array($thislinetimestamps)) {
|
||||||
|
sort($thislinetimestamps);
|
||||||
|
foreach ($thislinetimestamps as $timestampkey => $timestamp) {
|
||||||
|
if (isset($Lyrics3data['synchedlyrics'][$timestamp])) {
|
||||||
|
// timestamps only have a 1-second resolution, it's possible that multiple lines
|
||||||
|
// could have the same timestamp, if so, append
|
||||||
|
$Lyrics3data['synchedlyrics'][$timestamp] .= "\r\n".$lyricline;
|
||||||
|
} else {
|
||||||
|
$Lyrics3data['synchedlyrics'][$timestamp] = $lyricline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$Lyrics3data['unsynchedlyrics'] = implode("\r\n", $notimestamplyricsarray);
|
||||||
|
if (isset($Lyrics3data['synchedlyrics']) && is_array($Lyrics3data['synchedlyrics'])) {
|
||||||
|
ksort($Lyrics3data['synchedlyrics']);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function IntString2Bool($char) {
|
||||||
|
if ($char == '1') {
|
||||||
|
return true;
|
||||||
|
} elseif ($char == '0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
766
soundmap/api/module.tag.xmp.php
Normal file
@ -0,0 +1,766 @@
|
|||||||
|
<?php
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/// getID3() by James Heinrich <info@getid3.org> //
|
||||||
|
// available at http://getid3.sourceforge.net //
|
||||||
|
// or http://www.getid3.org //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// See readme.txt for more details //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// module.tag.xmp.php //
|
||||||
|
// module for analyzing XMP metadata (e.g. in JPEG files) //
|
||||||
|
// dependencies: NONE //
|
||||||
|
// //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// Module originally written [2009-Mar-26] by //
|
||||||
|
// Nigel Barnes <ngbarnesØhotmail*com> //
|
||||||
|
// Bundled into getID3 with permission //
|
||||||
|
// called by getID3 in module.graphic.jpg.php //
|
||||||
|
// ///
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* SWISScenter Source Nigel Barnes
|
||||||
|
*
|
||||||
|
* Provides functions for reading information from the 'APP1' Extensible Metadata
|
||||||
|
* Platform (XMP) segment of JPEG format files.
|
||||||
|
* This XMP segment is XML based and contains the Resource Description Framework (RDF)
|
||||||
|
* data, which itself can contain the Dublin Core Metadata Initiative (DCMI) information.
|
||||||
|
*
|
||||||
|
* This code uses segments from the JPEG Metadata Toolkit project by Evan Hunter.
|
||||||
|
*************************************************************************************************/
|
||||||
|
class Image_XMP
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
* The name of the image file that contains the XMP fields to extract and modify.
|
||||||
|
* @see Image_XMP()
|
||||||
|
*/
|
||||||
|
var $_sFilename = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
* The XMP fields that were extracted from the image or updated by this class.
|
||||||
|
* @see getAllTags()
|
||||||
|
*/
|
||||||
|
var $_aXMP = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean
|
||||||
|
* True if an APP1 segment was found to contain XMP metadata.
|
||||||
|
* @see isValid()
|
||||||
|
*/
|
||||||
|
var $_bXMPParse = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the status of XMP parsing during instantiation
|
||||||
|
*
|
||||||
|
* You'll normally want to call this method before trying to get XMP fields.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
* Returns true if an APP1 segment was found to contain XMP metadata.
|
||||||
|
*/
|
||||||
|
function isValid()
|
||||||
|
{
|
||||||
|
return $this->_bXMPParse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a copy of all XMP tags extracted from the image
|
||||||
|
*
|
||||||
|
* @return array - An array of XMP fields as it extracted by the XMPparse() function
|
||||||
|
*/
|
||||||
|
function getAllTags()
|
||||||
|
{
|
||||||
|
return $this->_aXMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads all the JPEG header segments from an JPEG image file into an array
|
||||||
|
*
|
||||||
|
* @param string $filename - the filename of the JPEG file to read
|
||||||
|
* @return array $headerdata - Array of JPEG header segments
|
||||||
|
* @return boolean FALSE - if headers could not be read
|
||||||
|
*/
|
||||||
|
function _get_jpeg_header_data($filename)
|
||||||
|
{
|
||||||
|
// prevent refresh from aborting file operations and hosing file
|
||||||
|
ignore_user_abort(true);
|
||||||
|
|
||||||
|
// Attempt to open the jpeg file - the at symbol supresses the error message about
|
||||||
|
// not being able to open files. The file_exists would have been used, but it
|
||||||
|
// does not work with files fetched over http or ftp.
|
||||||
|
if (is_readable($filename) && is_file($filename) && ($filehnd = fopen($filename, 'rb'))) {
|
||||||
|
// great
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the first two characters
|
||||||
|
$data = fread($filehnd, 2);
|
||||||
|
|
||||||
|
// Check that the first two characters are 0xFF 0xD8 (SOI - Start of image)
|
||||||
|
if ($data != "\xFF\xD8")
|
||||||
|
{
|
||||||
|
// No SOI (FF D8) at start of file - This probably isn't a JPEG file - close file and return;
|
||||||
|
echo '<p>This probably is not a JPEG file</p>'."\n";
|
||||||
|
fclose($filehnd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the third character
|
||||||
|
$data = fread($filehnd, 2);
|
||||||
|
|
||||||
|
// Check that the third character is 0xFF (Start of first segment header)
|
||||||
|
if ($data{0} != "\xFF")
|
||||||
|
{
|
||||||
|
// NO FF found - close file and return - JPEG is probably corrupted
|
||||||
|
fclose($filehnd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flag that we havent yet hit the compressed image data
|
||||||
|
$hit_compressed_image_data = false;
|
||||||
|
|
||||||
|
// Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
|
||||||
|
// 2) we have hit the compressed image data (no more headers are allowed after data)
|
||||||
|
// 3) or end of file is hit
|
||||||
|
|
||||||
|
while (($data{1} != "\xD9") && (!$hit_compressed_image_data) && (!feof($filehnd)))
|
||||||
|
{
|
||||||
|
// Found a segment to look at.
|
||||||
|
// Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
|
||||||
|
if ((ord($data{1}) < 0xD0) || (ord($data{1}) > 0xD7))
|
||||||
|
{
|
||||||
|
// Segment isn't a Restart marker
|
||||||
|
// Read the next two bytes (size)
|
||||||
|
$sizestr = fread($filehnd, 2);
|
||||||
|
|
||||||
|
// convert the size bytes to an integer
|
||||||
|
$decodedsize = unpack('nsize', $sizestr);
|
||||||
|
|
||||||
|
// Save the start position of the data
|
||||||
|
$segdatastart = ftell($filehnd);
|
||||||
|
|
||||||
|
// Read the segment data with length indicated by the previously read size
|
||||||
|
$segdata = fread($filehnd, $decodedsize['size'] - 2);
|
||||||
|
|
||||||
|
// Store the segment information in the output array
|
||||||
|
$headerdata[] = array(
|
||||||
|
'SegType' => ord($data{1}),
|
||||||
|
'SegName' => $GLOBALS['JPEG_Segment_Names'][ord($data{1})],
|
||||||
|
'SegDataStart' => $segdatastart,
|
||||||
|
'SegData' => $segdata,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
|
||||||
|
if ($data{1} == "\xDA")
|
||||||
|
{
|
||||||
|
// Flag that we have hit the compressed image data - exit loop as no more headers available.
|
||||||
|
$hit_compressed_image_data = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not an SOS - Read the next two bytes - should be the segment marker for the next segment
|
||||||
|
$data = fread($filehnd, 2);
|
||||||
|
|
||||||
|
// Check that the first byte of the two is 0xFF as it should be for a marker
|
||||||
|
if ($data{0} != "\xFF")
|
||||||
|
{
|
||||||
|
// NO FF found - close file and return - JPEG is probably corrupted
|
||||||
|
fclose($filehnd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close File
|
||||||
|
fclose($filehnd);
|
||||||
|
// Alow the user to abort from now on
|
||||||
|
ignore_user_abort(false);
|
||||||
|
|
||||||
|
// Return the header data retrieved
|
||||||
|
return $headerdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves XMP information from an APP1 JPEG segment and returns the raw XML text as a string.
|
||||||
|
*
|
||||||
|
* @param string $filename - the filename of the JPEG file to read
|
||||||
|
* @return string $xmp_data - the string of raw XML text
|
||||||
|
* @return boolean FALSE - if an APP 1 XMP segment could not be found, or if an error occured
|
||||||
|
*/
|
||||||
|
function _get_XMP_text($filename)
|
||||||
|
{
|
||||||
|
//Get JPEG header data
|
||||||
|
$jpeg_header_data = $this->_get_jpeg_header_data($filename);
|
||||||
|
|
||||||
|
//Cycle through the header segments
|
||||||
|
for ($i = 0; $i < count($jpeg_header_data); $i++)
|
||||||
|
{
|
||||||
|
// If we find an APP1 header,
|
||||||
|
if (strcmp($jpeg_header_data[$i]['SegName'], 'APP1') == 0)
|
||||||
|
{
|
||||||
|
// And if it has the Adobe XMP/RDF label (http://ns.adobe.com/xap/1.0/\x00) ,
|
||||||
|
if (strncmp($jpeg_header_data[$i]['SegData'], 'http://ns.adobe.com/xap/1.0/'."\x00", 29) == 0)
|
||||||
|
{
|
||||||
|
// Found a XMP/RDF block
|
||||||
|
// Return the XMP text
|
||||||
|
$xmp_data = substr($jpeg_header_data[$i]['SegData'], 29);
|
||||||
|
|
||||||
|
return trim($xmp_data); // trim() should not be neccesary, but some files found in the wild with null-terminated block (known samples from Apple Aperture) causes problems elsewhere (see http://www.getid3.org/phpBB3/viewtopic.php?f=4&t=1153)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string containing XMP data (XML), and returns an array
|
||||||
|
* which contains all the XMP (XML) information.
|
||||||
|
*
|
||||||
|
* @param string $xml_text - a string containing the XMP data (XML) to be parsed
|
||||||
|
* @return array $xmp_array - an array containing all xmp details retrieved.
|
||||||
|
* @return boolean FALSE - couldn't parse the XMP data
|
||||||
|
*/
|
||||||
|
function read_XMP_array_from_text($xmltext)
|
||||||
|
{
|
||||||
|
// Check if there actually is any text to parse
|
||||||
|
if (trim($xmltext) == '')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an instance of a xml parser to parse the XML text
|
||||||
|
$xml_parser = xml_parser_create('UTF-8');
|
||||||
|
|
||||||
|
// Change: Fixed problem that caused the whitespace (especially newlines) to be destroyed when converting xml text to an xml array, as of revision 1.10
|
||||||
|
|
||||||
|
// We would like to remove unneccessary white space, but this will also
|
||||||
|
// remove things like newlines (
) in the XML values, so white space
|
||||||
|
// will have to be removed later
|
||||||
|
if (xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 0) == false)
|
||||||
|
{
|
||||||
|
// Error setting case folding - destroy the parser and return
|
||||||
|
xml_parser_free($xml_parser);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to use XML code correctly we have to turn case folding
|
||||||
|
// (uppercasing) off. XML is case sensitive and upper
|
||||||
|
// casing is in reality XML standards violation
|
||||||
|
if (xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0) == false)
|
||||||
|
{
|
||||||
|
// Error setting case folding - destroy the parser and return
|
||||||
|
xml_parser_free($xml_parser);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the XML text into a array structure
|
||||||
|
if (xml_parse_into_struct($xml_parser, $xmltext, $values, $tags) == 0)
|
||||||
|
{
|
||||||
|
// Error Parsing XML - destroy the parser and return
|
||||||
|
xml_parser_free($xml_parser);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the xml parser
|
||||||
|
xml_parser_free($xml_parser);
|
||||||
|
|
||||||
|
// Clear the output array
|
||||||
|
$xmp_array = array();
|
||||||
|
|
||||||
|
// The XMP data has now been parsed into an array ...
|
||||||
|
|
||||||
|
// Cycle through each of the array elements
|
||||||
|
$current_property = ''; // current property being processed
|
||||||
|
$container_index = -1; // -1 = no container open, otherwise index of container content
|
||||||
|
foreach ($values as $xml_elem)
|
||||||
|
{
|
||||||
|
// Syntax and Class names
|
||||||
|
switch ($xml_elem['tag'])
|
||||||
|
{
|
||||||
|
case 'x:xmpmeta':
|
||||||
|
// only defined attribute is x:xmptk written by Adobe XMP Toolkit; value is the version of the toolkit
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rdf:RDF':
|
||||||
|
// required element immediately within x:xmpmeta; no data here
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rdf:Description':
|
||||||
|
switch ($xml_elem['type'])
|
||||||
|
{
|
||||||
|
case 'open':
|
||||||
|
case 'complete':
|
||||||
|
if (array_key_exists('attributes', $xml_elem))
|
||||||
|
{
|
||||||
|
// rdf:Description may contain wanted attributes
|
||||||
|
foreach (array_keys($xml_elem['attributes']) as $key)
|
||||||
|
{
|
||||||
|
// Check whether we want this details from this attribute
|
||||||
|
if (in_array($key, $GLOBALS['XMP_tag_captions']))
|
||||||
|
{
|
||||||
|
// Attribute wanted
|
||||||
|
$xmp_array[$key] = $xml_elem['attributes'][$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'cdata':
|
||||||
|
case 'close':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'rdf:ID':
|
||||||
|
case 'rdf:nodeID':
|
||||||
|
// Attributes are ignored
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rdf:li':
|
||||||
|
// Property member
|
||||||
|
if ($xml_elem['type'] == 'complete')
|
||||||
|
{
|
||||||
|
if (array_key_exists('attributes', $xml_elem))
|
||||||
|
{
|
||||||
|
// If Lang Alt (language alternatives) then ensure we take the default language
|
||||||
|
if (isset($xml_elem['attributes']['xml:lang']) && ($xml_elem['attributes']['xml:lang'] != 'x-default'))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($current_property != '')
|
||||||
|
{
|
||||||
|
$xmp_array[$current_property][$container_index] = (isset($xml_elem['value']) ? $xml_elem['value'] : '');
|
||||||
|
$container_index += 1;
|
||||||
|
}
|
||||||
|
//else unidentified attribute!!
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'rdf:Seq':
|
||||||
|
case 'rdf:Bag':
|
||||||
|
case 'rdf:Alt':
|
||||||
|
// Container found
|
||||||
|
switch ($xml_elem['type'])
|
||||||
|
{
|
||||||
|
case 'open':
|
||||||
|
$container_index = 0;
|
||||||
|
break;
|
||||||
|
case 'close':
|
||||||
|
$container_index = -1;
|
||||||
|
break;
|
||||||
|
case 'cdata':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Check whether we want the details from this attribute
|
||||||
|
if (in_array($xml_elem['tag'], $GLOBALS['XMP_tag_captions']))
|
||||||
|
{
|
||||||
|
switch ($xml_elem['type'])
|
||||||
|
{
|
||||||
|
case 'open':
|
||||||
|
// open current element
|
||||||
|
$current_property = $xml_elem['tag'];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'close':
|
||||||
|
// close current element
|
||||||
|
$current_property = '';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'complete':
|
||||||
|
// store attribute value
|
||||||
|
$xmp_array[$xml_elem['tag']] = (isset($xml_elem['value']) ? $xml_elem['value'] : '');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'cdata':
|
||||||
|
// ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return $xmp_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string - Name of the image file to access and extract XMP information from.
|
||||||
|
*/
|
||||||
|
function Image_XMP($sFilename)
|
||||||
|
{
|
||||||
|
$this->_sFilename = $sFilename;
|
||||||
|
|
||||||
|
if (is_file($this->_sFilename))
|
||||||
|
{
|
||||||
|
// Get XMP data
|
||||||
|
$xmp_data = $this->_get_XMP_text($sFilename);
|
||||||
|
if ($xmp_data)
|
||||||
|
{
|
||||||
|
$this->_aXMP = $this->read_XMP_array_from_text($xmp_data);
|
||||||
|
$this->_bXMPParse = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Variable: XMP_tag_captions
|
||||||
|
*
|
||||||
|
* The Property names of all known XMP fields.
|
||||||
|
* Note: this is a full list with unrequired properties commented out.
|
||||||
|
*/
|
||||||
|
$GLOBALS['XMP_tag_captions'] = array(
|
||||||
|
// IPTC Core
|
||||||
|
'Iptc4xmpCore:CiAdrCity',
|
||||||
|
'Iptc4xmpCore:CiAdrCtry',
|
||||||
|
'Iptc4xmpCore:CiAdrExtadr',
|
||||||
|
'Iptc4xmpCore:CiAdrPcode',
|
||||||
|
'Iptc4xmpCore:CiAdrRegion',
|
||||||
|
'Iptc4xmpCore:CiEmailWork',
|
||||||
|
'Iptc4xmpCore:CiTelWork',
|
||||||
|
'Iptc4xmpCore:CiUrlWork',
|
||||||
|
'Iptc4xmpCore:CountryCode',
|
||||||
|
'Iptc4xmpCore:CreatorContactInfo',
|
||||||
|
'Iptc4xmpCore:IntellectualGenre',
|
||||||
|
'Iptc4xmpCore:Location',
|
||||||
|
'Iptc4xmpCore:Scene',
|
||||||
|
'Iptc4xmpCore:SubjectCode',
|
||||||
|
// Dublin Core Schema
|
||||||
|
'dc:contributor',
|
||||||
|
'dc:coverage',
|
||||||
|
'dc:creator',
|
||||||
|
'dc:date',
|
||||||
|
'dc:description',
|
||||||
|
'dc:format',
|
||||||
|
'dc:identifier',
|
||||||
|
'dc:language',
|
||||||
|
'dc:publisher',
|
||||||
|
'dc:relation',
|
||||||
|
'dc:rights',
|
||||||
|
'dc:source',
|
||||||
|
'dc:subject',
|
||||||
|
'dc:title',
|
||||||
|
'dc:type',
|
||||||
|
// XMP Basic Schema
|
||||||
|
'xmp:Advisory',
|
||||||
|
'xmp:BaseURL',
|
||||||
|
'xmp:CreateDate',
|
||||||
|
'xmp:CreatorTool',
|
||||||
|
'xmp:Identifier',
|
||||||
|
'xmp:Label',
|
||||||
|
'xmp:MetadataDate',
|
||||||
|
'xmp:ModifyDate',
|
||||||
|
'xmp:Nickname',
|
||||||
|
'xmp:Rating',
|
||||||
|
'xmp:Thumbnails',
|
||||||
|
'xmpidq:Scheme',
|
||||||
|
// XMP Rights Management Schema
|
||||||
|
'xmpRights:Certificate',
|
||||||
|
'xmpRights:Marked',
|
||||||
|
'xmpRights:Owner',
|
||||||
|
'xmpRights:UsageTerms',
|
||||||
|
'xmpRights:WebStatement',
|
||||||
|
// These are not in spec but Photoshop CS seems to use them
|
||||||
|
'xap:Advisory',
|
||||||
|
'xap:BaseURL',
|
||||||
|
'xap:CreateDate',
|
||||||
|
'xap:CreatorTool',
|
||||||
|
'xap:Identifier',
|
||||||
|
'xap:MetadataDate',
|
||||||
|
'xap:ModifyDate',
|
||||||
|
'xap:Nickname',
|
||||||
|
'xap:Rating',
|
||||||
|
'xap:Thumbnails',
|
||||||
|
'xapidq:Scheme',
|
||||||
|
'xapRights:Certificate',
|
||||||
|
'xapRights:Copyright',
|
||||||
|
'xapRights:Marked',
|
||||||
|
'xapRights:Owner',
|
||||||
|
'xapRights:UsageTerms',
|
||||||
|
'xapRights:WebStatement',
|
||||||
|
// XMP Media Management Schema
|
||||||
|
'xapMM:DerivedFrom',
|
||||||
|
'xapMM:DocumentID',
|
||||||
|
'xapMM:History',
|
||||||
|
'xapMM:InstanceID',
|
||||||
|
'xapMM:ManagedFrom',
|
||||||
|
'xapMM:Manager',
|
||||||
|
'xapMM:ManageTo',
|
||||||
|
'xapMM:ManageUI',
|
||||||
|
'xapMM:ManagerVariant',
|
||||||
|
'xapMM:RenditionClass',
|
||||||
|
'xapMM:RenditionParams',
|
||||||
|
'xapMM:VersionID',
|
||||||
|
'xapMM:Versions',
|
||||||
|
'xapMM:LastURL',
|
||||||
|
'xapMM:RenditionOf',
|
||||||
|
'xapMM:SaveID',
|
||||||
|
// XMP Basic Job Ticket Schema
|
||||||
|
'xapBJ:JobRef',
|
||||||
|
// XMP Paged-Text Schema
|
||||||
|
'xmpTPg:MaxPageSize',
|
||||||
|
'xmpTPg:NPages',
|
||||||
|
'xmpTPg:Fonts',
|
||||||
|
'xmpTPg:Colorants',
|
||||||
|
'xmpTPg:PlateNames',
|
||||||
|
// Adobe PDF Schema
|
||||||
|
'pdf:Keywords',
|
||||||
|
'pdf:PDFVersion',
|
||||||
|
'pdf:Producer',
|
||||||
|
// Photoshop Schema
|
||||||
|
'photoshop:AuthorsPosition',
|
||||||
|
'photoshop:CaptionWriter',
|
||||||
|
'photoshop:Category',
|
||||||
|
'photoshop:City',
|
||||||
|
'photoshop:Country',
|
||||||
|
'photoshop:Credit',
|
||||||
|
'photoshop:DateCreated',
|
||||||
|
'photoshop:Headline',
|
||||||
|
'photoshop:History',
|
||||||
|
// Not in XMP spec
|
||||||
|
'photoshop:Instructions',
|
||||||
|
'photoshop:Source',
|
||||||
|
'photoshop:State',
|
||||||
|
'photoshop:SupplementalCategories',
|
||||||
|
'photoshop:TransmissionReference',
|
||||||
|
'photoshop:Urgency',
|
||||||
|
// EXIF Schemas
|
||||||
|
'tiff:ImageWidth',
|
||||||
|
'tiff:ImageLength',
|
||||||
|
'tiff:BitsPerSample',
|
||||||
|
'tiff:Compression',
|
||||||
|
'tiff:PhotometricInterpretation',
|
||||||
|
'tiff:Orientation',
|
||||||
|
'tiff:SamplesPerPixel',
|
||||||
|
'tiff:PlanarConfiguration',
|
||||||
|
'tiff:YCbCrSubSampling',
|
||||||
|
'tiff:YCbCrPositioning',
|
||||||
|
'tiff:XResolution',
|
||||||
|
'tiff:YResolution',
|
||||||
|
'tiff:ResolutionUnit',
|
||||||
|
'tiff:TransferFunction',
|
||||||
|
'tiff:WhitePoint',
|
||||||
|
'tiff:PrimaryChromaticities',
|
||||||
|
'tiff:YCbCrCoefficients',
|
||||||
|
'tiff:ReferenceBlackWhite',
|
||||||
|
'tiff:DateTime',
|
||||||
|
'tiff:ImageDescription',
|
||||||
|
'tiff:Make',
|
||||||
|
'tiff:Model',
|
||||||
|
'tiff:Software',
|
||||||
|
'tiff:Artist',
|
||||||
|
'tiff:Copyright',
|
||||||
|
'exif:ExifVersion',
|
||||||
|
'exif:FlashpixVersion',
|
||||||
|
'exif:ColorSpace',
|
||||||
|
'exif:ComponentsConfiguration',
|
||||||
|
'exif:CompressedBitsPerPixel',
|
||||||
|
'exif:PixelXDimension',
|
||||||
|
'exif:PixelYDimension',
|
||||||
|
'exif:MakerNote',
|
||||||
|
'exif:UserComment',
|
||||||
|
'exif:RelatedSoundFile',
|
||||||
|
'exif:DateTimeOriginal',
|
||||||
|
'exif:DateTimeDigitized',
|
||||||
|
'exif:ExposureTime',
|
||||||
|
'exif:FNumber',
|
||||||
|
'exif:ExposureProgram',
|
||||||
|
'exif:SpectralSensitivity',
|
||||||
|
'exif:ISOSpeedRatings',
|
||||||
|
'exif:OECF',
|
||||||
|
'exif:ShutterSpeedValue',
|
||||||
|
'exif:ApertureValue',
|
||||||
|
'exif:BrightnessValue',
|
||||||
|
'exif:ExposureBiasValue',
|
||||||
|
'exif:MaxApertureValue',
|
||||||
|
'exif:SubjectDistance',
|
||||||
|
'exif:MeteringMode',
|
||||||
|
'exif:LightSource',
|
||||||
|
'exif:Flash',
|
||||||
|
'exif:FocalLength',
|
||||||
|
'exif:SubjectArea',
|
||||||
|
'exif:FlashEnergy',
|
||||||
|
'exif:SpatialFrequencyResponse',
|
||||||
|
'exif:FocalPlaneXResolution',
|
||||||
|
'exif:FocalPlaneYResolution',
|
||||||
|
'exif:FocalPlaneResolutionUnit',
|
||||||
|
'exif:SubjectLocation',
|
||||||
|
'exif:SensingMethod',
|
||||||
|
'exif:FileSource',
|
||||||
|
'exif:SceneType',
|
||||||
|
'exif:CFAPattern',
|
||||||
|
'exif:CustomRendered',
|
||||||
|
'exif:ExposureMode',
|
||||||
|
'exif:WhiteBalance',
|
||||||
|
'exif:DigitalZoomRatio',
|
||||||
|
'exif:FocalLengthIn35mmFilm',
|
||||||
|
'exif:SceneCaptureType',
|
||||||
|
'exif:GainControl',
|
||||||
|
'exif:Contrast',
|
||||||
|
'exif:Saturation',
|
||||||
|
'exif:Sharpness',
|
||||||
|
'exif:DeviceSettingDescription',
|
||||||
|
'exif:SubjectDistanceRange',
|
||||||
|
'exif:ImageUniqueID',
|
||||||
|
'exif:GPSVersionID',
|
||||||
|
'exif:GPSLatitude',
|
||||||
|
'exif:GPSLongitude',
|
||||||
|
'exif:GPSAltitudeRef',
|
||||||
|
'exif:GPSAltitude',
|
||||||
|
'exif:GPSTimeStamp',
|
||||||
|
'exif:GPSSatellites',
|
||||||
|
'exif:GPSStatus',
|
||||||
|
'exif:GPSMeasureMode',
|
||||||
|
'exif:GPSDOP',
|
||||||
|
'exif:GPSSpeedRef',
|
||||||
|
'exif:GPSSpeed',
|
||||||
|
'exif:GPSTrackRef',
|
||||||
|
'exif:GPSTrack',
|
||||||
|
'exif:GPSImgDirectionRef',
|
||||||
|
'exif:GPSImgDirection',
|
||||||
|
'exif:GPSMapDatum',
|
||||||
|
'exif:GPSDestLatitude',
|
||||||
|
'exif:GPSDestLongitude',
|
||||||
|
'exif:GPSDestBearingRef',
|
||||||
|
'exif:GPSDestBearing',
|
||||||
|
'exif:GPSDestDistanceRef',
|
||||||
|
'exif:GPSDestDistance',
|
||||||
|
'exif:GPSProcessingMethod',
|
||||||
|
'exif:GPSAreaInformation',
|
||||||
|
'exif:GPSDifferential',
|
||||||
|
'stDim:w',
|
||||||
|
'stDim:h',
|
||||||
|
'stDim:unit',
|
||||||
|
'xapGImg:height',
|
||||||
|
'xapGImg:width',
|
||||||
|
'xapGImg:format',
|
||||||
|
'xapGImg:image',
|
||||||
|
'stEvt:action',
|
||||||
|
'stEvt:instanceID',
|
||||||
|
'stEvt:parameters',
|
||||||
|
'stEvt:softwareAgent',
|
||||||
|
'stEvt:when',
|
||||||
|
'stRef:instanceID',
|
||||||
|
'stRef:documentID',
|
||||||
|
'stRef:versionID',
|
||||||
|
'stRef:renditionClass',
|
||||||
|
'stRef:renditionParams',
|
||||||
|
'stRef:manager',
|
||||||
|
'stRef:managerVariant',
|
||||||
|
'stRef:manageTo',
|
||||||
|
'stRef:manageUI',
|
||||||
|
'stVer:comments',
|
||||||
|
'stVer:event',
|
||||||
|
'stVer:modifyDate',
|
||||||
|
'stVer:modifier',
|
||||||
|
'stVer:version',
|
||||||
|
'stJob:name',
|
||||||
|
'stJob:id',
|
||||||
|
'stJob:url',
|
||||||
|
// Exif Flash
|
||||||
|
'exif:Fired',
|
||||||
|
'exif:Return',
|
||||||
|
'exif:Mode',
|
||||||
|
'exif:Function',
|
||||||
|
'exif:RedEyeMode',
|
||||||
|
// Exif OECF/SFR
|
||||||
|
'exif:Columns',
|
||||||
|
'exif:Rows',
|
||||||
|
'exif:Names',
|
||||||
|
'exif:Values',
|
||||||
|
// Exif CFAPattern
|
||||||
|
'exif:Columns',
|
||||||
|
'exif:Rows',
|
||||||
|
'exif:Values',
|
||||||
|
// Exif DeviceSettings
|
||||||
|
'exif:Columns',
|
||||||
|
'exif:Rows',
|
||||||
|
'exif:Settings',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Variable: JPEG_Segment_Names
|
||||||
|
*
|
||||||
|
* The names of the JPEG segment markers, indexed by their marker number
|
||||||
|
*/
|
||||||
|
$GLOBALS['JPEG_Segment_Names'] = array(
|
||||||
|
0x01 => 'TEM',
|
||||||
|
0x02 => 'RES',
|
||||||
|
0xC0 => 'SOF0',
|
||||||
|
0xC1 => 'SOF1',
|
||||||
|
0xC2 => 'SOF2',
|
||||||
|
0xC3 => 'SOF4',
|
||||||
|
0xC4 => 'DHT',
|
||||||
|
0xC5 => 'SOF5',
|
||||||
|
0xC6 => 'SOF6',
|
||||||
|
0xC7 => 'SOF7',
|
||||||
|
0xC8 => 'JPG',
|
||||||
|
0xC9 => 'SOF9',
|
||||||
|
0xCA => 'SOF10',
|
||||||
|
0xCB => 'SOF11',
|
||||||
|
0xCC => 'DAC',
|
||||||
|
0xCD => 'SOF13',
|
||||||
|
0xCE => 'SOF14',
|
||||||
|
0xCF => 'SOF15',
|
||||||
|
0xD0 => 'RST0',
|
||||||
|
0xD1 => 'RST1',
|
||||||
|
0xD2 => 'RST2',
|
||||||
|
0xD3 => 'RST3',
|
||||||
|
0xD4 => 'RST4',
|
||||||
|
0xD5 => 'RST5',
|
||||||
|
0xD6 => 'RST6',
|
||||||
|
0xD7 => 'RST7',
|
||||||
|
0xD8 => 'SOI',
|
||||||
|
0xD9 => 'EOI',
|
||||||
|
0xDA => 'SOS',
|
||||||
|
0xDB => 'DQT',
|
||||||
|
0xDC => 'DNL',
|
||||||
|
0xDD => 'DRI',
|
||||||
|
0xDE => 'DHP',
|
||||||
|
0xDF => 'EXP',
|
||||||
|
0xE0 => 'APP0',
|
||||||
|
0xE1 => 'APP1',
|
||||||
|
0xE2 => 'APP2',
|
||||||
|
0xE3 => 'APP3',
|
||||||
|
0xE4 => 'APP4',
|
||||||
|
0xE5 => 'APP5',
|
||||||
|
0xE6 => 'APP6',
|
||||||
|
0xE7 => 'APP7',
|
||||||
|
0xE8 => 'APP8',
|
||||||
|
0xE9 => 'APP9',
|
||||||
|
0xEA => 'APP10',
|
||||||
|
0xEB => 'APP11',
|
||||||
|
0xEC => 'APP12',
|
||||||
|
0xED => 'APP13',
|
||||||
|
0xEE => 'APP14',
|
||||||
|
0xEF => 'APP15',
|
||||||
|
0xF0 => 'JPG0',
|
||||||
|
0xF1 => 'JPG1',
|
||||||
|
0xF2 => 'JPG2',
|
||||||
|
0xF3 => 'JPG3',
|
||||||
|
0xF4 => 'JPG4',
|
||||||
|
0xF5 => 'JPG5',
|
||||||
|
0xF6 => 'JPG6',
|
||||||
|
0xF7 => 'JPG7',
|
||||||
|
0xF8 => 'JPG8',
|
||||||
|
0xF9 => 'JPG9',
|
||||||
|
0xFA => 'JPG10',
|
||||||
|
0xFB => 'JPG11',
|
||||||
|
0xFC => 'JPG12',
|
||||||
|
0xFD => 'JPG13',
|
||||||
|
0xFE => 'COM',
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
448
soundmap/css/jplayer.blue.monday.css
Normal file
@ -0,0 +1,448 @@
|
|||||||
|
/*
|
||||||
|
* Skin for jPlayer Plugin (jQuery JavaScript Library)
|
||||||
|
* http://www.happyworm.com/jquery/jplayer
|
||||||
|
*
|
||||||
|
* Skin Name: Blue Monday
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Happyworm Ltd
|
||||||
|
* Dual licensed under the MIT and GPL licenses.
|
||||||
|
* - http://www.opensource.org/licenses/mit-license.php
|
||||||
|
* - http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
* Author: Silvia Benvenuti
|
||||||
|
* Skin Version: 3.0 (jPlayer 2.0.0)
|
||||||
|
* Date: 20th December 2010
|
||||||
|
*/
|
||||||
|
|
||||||
|
div.jp-audio,
|
||||||
|
div.jp-video {
|
||||||
|
|
||||||
|
/* Edit the font-size to counteract inherited font sizing.
|
||||||
|
* Eg. 1.25em = 1 / 0.8em
|
||||||
|
*/
|
||||||
|
|
||||||
|
font-size:1.25em;
|
||||||
|
|
||||||
|
font-family:Verdana, Arial, sans-serif;
|
||||||
|
line-height:1.6;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
div.jp-audio {
|
||||||
|
width:420px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p {
|
||||||
|
width:480px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p {
|
||||||
|
width:640px;
|
||||||
|
}
|
||||||
|
div.jp-interface {
|
||||||
|
position: relative;
|
||||||
|
background-color:#eee;
|
||||||
|
/* width:418px; */
|
||||||
|
width:100%;
|
||||||
|
border:1px solid #009be3;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single div.jp-interface {
|
||||||
|
height:80px;
|
||||||
|
border-bottom:none;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist div.jp-interface {
|
||||||
|
height:80px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-type-single div.jp-interface {
|
||||||
|
height:60px;
|
||||||
|
border-bottom:none;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-type-playlist div.jp-interface {
|
||||||
|
height:60px;
|
||||||
|
}
|
||||||
|
div.jp-interface ul.jp-controls {
|
||||||
|
list-style-type:none;
|
||||||
|
padding:0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
div.jp-interface ul.jp-controls li {
|
||||||
|
/* position: absolute; */
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
div.jp-interface ul.jp-controls a {
|
||||||
|
position: absolute;
|
||||||
|
overflow:hidden;
|
||||||
|
text-indent:-9999px;
|
||||||
|
}
|
||||||
|
a.jp-play,
|
||||||
|
a.jp-pause {
|
||||||
|
width:40px;
|
||||||
|
height:40px;
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single a.jp-play,
|
||||||
|
div.jp-audio div.jp-type-single a.jp-pause {
|
||||||
|
top:20px;
|
||||||
|
left:40px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-play,
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-pause {
|
||||||
|
top:20px;
|
||||||
|
left:48px;
|
||||||
|
}
|
||||||
|
div.jp-video a.jp-play,
|
||||||
|
div.jp-video a.jp-pause {
|
||||||
|
top:15px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-single a.jp-play,
|
||||||
|
div.jp-video-270p div.jp-type-single a.jp-pause {
|
||||||
|
left:195px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-play,
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-pause {
|
||||||
|
left:220px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-single a.jp-play,
|
||||||
|
div.jp-video-360p div.jp-type-single a.jp-pause {
|
||||||
|
left:275px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-play,
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-pause {
|
||||||
|
left:300px;
|
||||||
|
}
|
||||||
|
a.jp-play {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
a.jp-play:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -41px 0 no-repeat;
|
||||||
|
}
|
||||||
|
a.jp-pause {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -42px no-repeat;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
a.jp-pause:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -41px -42px no-repeat;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single a.jp-stop {
|
||||||
|
top:26px;
|
||||||
|
left:90px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-stop {
|
||||||
|
top:26px;
|
||||||
|
left:126px;
|
||||||
|
}
|
||||||
|
div.jp-video a.jp-stop {
|
||||||
|
top:21px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-single a.jp-stop {
|
||||||
|
left:245px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-stop {
|
||||||
|
left:298px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-single a.jp-stop {
|
||||||
|
left:325px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-stop {
|
||||||
|
left:378px;
|
||||||
|
}
|
||||||
|
a.jp-stop {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -83px no-repeat;
|
||||||
|
width:28px;
|
||||||
|
height:28px;
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
a.jp-stop:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -29px -83px no-repeat;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-previous {
|
||||||
|
left:20px;
|
||||||
|
top:26px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-type-playlist a.jp-previous {
|
||||||
|
top:21px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-previous {
|
||||||
|
left:192px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-previous {
|
||||||
|
left:272px;
|
||||||
|
}
|
||||||
|
a.jp-previous {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -112px no-repeat;
|
||||||
|
width:28px;
|
||||||
|
height:28px;
|
||||||
|
}
|
||||||
|
a.jp-previous:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -29px -112px no-repeat;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-next {
|
||||||
|
left:88px;
|
||||||
|
top:26px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-type-playlist a.jp-next {
|
||||||
|
top:21px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-next {
|
||||||
|
left:260px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-next {
|
||||||
|
left:340px;
|
||||||
|
}
|
||||||
|
a.jp-next {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -141px no-repeat;
|
||||||
|
width:28px;
|
||||||
|
height:28px;
|
||||||
|
}
|
||||||
|
a.jp-next:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -29px -141px no-repeat;
|
||||||
|
}
|
||||||
|
div.jp-progress {
|
||||||
|
position: absolute;
|
||||||
|
overflow:hidden;
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single div.jp-progress {
|
||||||
|
top:32px;
|
||||||
|
left:130px;
|
||||||
|
width:122px;
|
||||||
|
height:15px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist div.jp-progress {
|
||||||
|
top:32px;
|
||||||
|
left:164px;
|
||||||
|
width:122px;
|
||||||
|
height:15px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-progress {
|
||||||
|
top:0px;
|
||||||
|
left:0px;
|
||||||
|
width:100%;
|
||||||
|
height:10px;
|
||||||
|
}
|
||||||
|
div.jp-seek-bar {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -202px repeat-x;
|
||||||
|
width:0px;
|
||||||
|
/* height:15px; */
|
||||||
|
height:100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
div.jp-play-bar {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -218px repeat-x ;
|
||||||
|
width:0px;
|
||||||
|
/* height:15px; */
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The seeking class is added/removed inside jPlayer */
|
||||||
|
div.jp-seeking-bg {
|
||||||
|
background: url("../img/pbar-ani.gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
a.jp-mute,
|
||||||
|
a.jp-unmute {
|
||||||
|
width:18px;
|
||||||
|
height:15px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single a.jp-mute,
|
||||||
|
div.jp-audio div.jp-type-single a.jp-unmute {
|
||||||
|
top:32px;
|
||||||
|
left:274px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-mute,
|
||||||
|
div.jp-audio div.jp-type-playlist a.jp-unmute {
|
||||||
|
top:32px;
|
||||||
|
left:296px;
|
||||||
|
}
|
||||||
|
div.jp-video a.jp-mute,
|
||||||
|
div.jp-video a.jp-unmute {
|
||||||
|
top:27px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-single a.jp-mute,
|
||||||
|
div.jp-video-270p div.jp-type-single a.jp-unmute {
|
||||||
|
left:304px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-unmute,
|
||||||
|
div.jp-video-270p div.jp-type-playlist a.jp-mute {
|
||||||
|
left:363px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-single a.jp-mute,
|
||||||
|
div.jp-video-360p div.jp-type-single a.jp-unmute {
|
||||||
|
left:384px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-mute,
|
||||||
|
div.jp-video-360p div.jp-type-playlist a.jp-unmute {
|
||||||
|
left:443px;
|
||||||
|
}
|
||||||
|
a.jp-mute {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -186px no-repeat;
|
||||||
|
}
|
||||||
|
a.jp-mute:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -19px -170px no-repeat;
|
||||||
|
}
|
||||||
|
a.jp-unmute {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -170px no-repeat;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
a.jp-unmute:hover {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") -19px -186px no-repeat;
|
||||||
|
}
|
||||||
|
div.jp-volume-bar {
|
||||||
|
position: absolute;
|
||||||
|
overflow:hidden;
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -250px repeat-x;
|
||||||
|
width:46px;
|
||||||
|
height:5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single div.jp-volume-bar {
|
||||||
|
top:37px;
|
||||||
|
left:302px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist div.jp-volume-bar {
|
||||||
|
top:37px;
|
||||||
|
left:324px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-volume-bar {
|
||||||
|
top:32px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-single div.jp-volume-bar {
|
||||||
|
left:332px;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-type-playlist div.jp-volume-bar {
|
||||||
|
left:391px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-single div.jp-volume-bar {
|
||||||
|
left:412px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-type-playlist div.jp-volume-bar {
|
||||||
|
left:471px;
|
||||||
|
}
|
||||||
|
div.jp-volume-bar-value {
|
||||||
|
background: url("../img/jplayer.blue.monday.jpg") 0 -256px repeat-x;
|
||||||
|
width:0px;
|
||||||
|
height:5px;
|
||||||
|
}
|
||||||
|
div.jp-current-time,
|
||||||
|
div.jp-duration {
|
||||||
|
position: absolute;
|
||||||
|
font-size:.64em;
|
||||||
|
font-style:oblique;
|
||||||
|
}
|
||||||
|
div.jp-duration {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-single div.jp-current-time,
|
||||||
|
div.jp-audio div.jp-type-single div.jp-duration {
|
||||||
|
top:49px;
|
||||||
|
left:130px;
|
||||||
|
width:122px;
|
||||||
|
}
|
||||||
|
div.jp-audio div.jp-type-playlist div.jp-current-time,
|
||||||
|
div.jp-audio div.jp-type-playlist div.jp-duration {
|
||||||
|
top:49px;
|
||||||
|
left:164px;
|
||||||
|
width:122px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-current-time,
|
||||||
|
div.jp-video div.jp-duration {
|
||||||
|
top:10px;
|
||||||
|
left:0px;
|
||||||
|
width:98%;
|
||||||
|
padding:0 1%;
|
||||||
|
}
|
||||||
|
div.jp-playlist {
|
||||||
|
/* width:418px; */
|
||||||
|
width:100%;
|
||||||
|
background-color:#ccc;
|
||||||
|
border:1px solid #009be3;
|
||||||
|
border-top:none;
|
||||||
|
}
|
||||||
|
div.jp-playlist ul {
|
||||||
|
list-style-type:none;
|
||||||
|
margin:0;
|
||||||
|
padding:0 20px;
|
||||||
|
/* background-color:#ccc; */
|
||||||
|
/* border:1px solid #009be3; */
|
||||||
|
/* border-top:none; */
|
||||||
|
/* width:378px; */
|
||||||
|
font-size:.72em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.jp-type-single div.jp-playlist li {
|
||||||
|
padding:5px 0 5px 20px;
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
div.jp-type-playlist div.jp-playlist li {
|
||||||
|
padding:5px 0 4px 20px;
|
||||||
|
border-bottom:1px solid #eee;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
div.jp-video div.jp-playlist li {
|
||||||
|
padding:5px 0 5px 20px;
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
div.jp-type-playlist div.jp-playlist li.jp-playlist-last {
|
||||||
|
padding:5px 0 5px 20px;
|
||||||
|
border-bottom:none;
|
||||||
|
}
|
||||||
|
div.jp-type-playlist div.jp-playlist li.jp-playlist-current {
|
||||||
|
list-style-type:square;
|
||||||
|
list-style-position:inside;
|
||||||
|
padding-left:8px;
|
||||||
|
}
|
||||||
|
div.jp-type-playlist div.jp-playlist a {
|
||||||
|
color: #666;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
div.jp-type-playlist div.jp-playlist a:hover {
|
||||||
|
color:#0d88c1;
|
||||||
|
}
|
||||||
|
div.jp-type-playlist div.jp-playlist a.jp-playlist-current {
|
||||||
|
color:#0d88c1;
|
||||||
|
}
|
||||||
|
div.jp-type-playlist div.jp-playlist div.jp-free-media {
|
||||||
|
display:inline;
|
||||||
|
margin-left:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-video div.jp-video-play {
|
||||||
|
background: transparent url("../img/jplayer.blue.monday.video.play.png") no-repeat center;
|
||||||
|
/* position: relative; */
|
||||||
|
position: absolute;
|
||||||
|
cursor:pointer;
|
||||||
|
z-index:2;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-video-play:hover {
|
||||||
|
background: transparent url("../img/jplayer.blue.monday.video.play.hover.png") no-repeat center;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-video-play {
|
||||||
|
top:-270px;
|
||||||
|
width:480px;
|
||||||
|
height:270px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-video-play {
|
||||||
|
top:-360px;
|
||||||
|
width:640px;
|
||||||
|
height:360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.jp-jplayer {
|
||||||
|
width:0px;
|
||||||
|
height:0px;
|
||||||
|
}
|
||||||
|
div.jp-video div.jp-jplayer {
|
||||||
|
border:1px solid #009be3;
|
||||||
|
border-bottom:none;
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
div.jp-video-270p div.jp-jplayer {
|
||||||
|
width:480px;
|
||||||
|
height:270px;
|
||||||
|
}
|
||||||
|
div.jp-video-360p div.jp-jplayer {
|
||||||
|
width:640px;
|
||||||
|
height:360px;
|
||||||
|
}
|
||||||
|
div.jp-jplayer {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
189
soundmap/css/jquery.datepicker.css
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
div.datepicker {
|
||||||
|
position: relative;
|
||||||
|
width: 196px;
|
||||||
|
height: 147px;
|
||||||
|
position: absolute;
|
||||||
|
cursor: default;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.datepickerContainer {
|
||||||
|
background: white;
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
.datepickerBorderT {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 0;
|
||||||
|
right: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: url(../img/datepicker_t.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderB {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
bottom: 0;
|
||||||
|
right: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: url(../img/datepicker_b.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderL {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 10px;
|
||||||
|
top: 10px;
|
||||||
|
width: 10px;
|
||||||
|
background: url(../img/datepicker_l.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderR {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 10px;
|
||||||
|
top: 10px;
|
||||||
|
width: 10px;
|
||||||
|
background: url(../img/datepicker_r.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderTL {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: url(../img/datepicker_tl.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderTR {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: url(../img/datepicker_tr.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderBL {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: url(../img/datepicker_bl.png);
|
||||||
|
}
|
||||||
|
.datepickerBorderBR {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: url(../img/datepicker_br.png);
|
||||||
|
}
|
||||||
|
.datepickerHidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
div.datepicker table {
|
||||||
|
border-collapse:collapse;
|
||||||
|
}
|
||||||
|
div.datepicker a {
|
||||||
|
color: #222;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: default;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
div.datepicker table td {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
div.datepicker th {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
div.datepicker tbody th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
div.datepicker tbody a {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.datepickerDays a {
|
||||||
|
width: 20px;
|
||||||
|
line-height: 16px;
|
||||||
|
height: 16px;
|
||||||
|
padding-right: 2px;
|
||||||
|
}
|
||||||
|
.datepickerYears a,
|
||||||
|
.datepickerMonths a{
|
||||||
|
width: 44px;
|
||||||
|
line-height: 36px;
|
||||||
|
height: 36px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
td.datepickerNotInMonth a {
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
tbody.datepickerDays td.datepickerSelected{
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
tbody.datepickerDays td.datepickerNotInMonth.datepickerSelected {
|
||||||
|
background: #17384d;
|
||||||
|
}
|
||||||
|
tbody.datepickerYears td.datepickerSelected,
|
||||||
|
tbody.datepickerMonths td.datepickerSelected{
|
||||||
|
background: #17384d;
|
||||||
|
}
|
||||||
|
div.datepicker a:hover,
|
||||||
|
div.datepicker a:hover {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
div.datepicker td.datepickerNotInMonth a:hover {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
div.datepicker tbody th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.datepickerSpace div {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
.datepickerGoNext a,
|
||||||
|
.datepickerGoPrev a,
|
||||||
|
.datepickerMonth a {
|
||||||
|
text-align: center;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.datepickerGoNext a {
|
||||||
|
float: right;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
.datepickerGoPrev a {
|
||||||
|
float: left;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
table.datepickerViewDays tbody.datepickerMonths,
|
||||||
|
table.datepickerViewDays tbody.datepickerYears {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
table.datepickerViewMonths tbody.datepickerDays,
|
||||||
|
table.datepickerViewMonths tbody.datepickerYears,
|
||||||
|
table.datepickerViewMonths tr.datepickerDoW {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
table.datepickerViewYears tbody.datepickerDays,
|
||||||
|
table.datepickerViewYears tbody.datepickerMonths,
|
||||||
|
table.datepickerViewYears tr.datepickerDoW {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
td.datepickerDisabled a,
|
||||||
|
td.datepickerDisabled.datepickerNotInMonth a{
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
td.datepickerDisabled a:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
td.datepickerSpecial a {
|
||||||
|
background: #700;
|
||||||
|
}
|
||||||
|
td.datepickerSpecial.datepickerSelected a {
|
||||||
|
background: #a00;
|
||||||
|
}
|
@ -1,2 +1,7 @@
|
|||||||
|
|
||||||
#map_canvas{width:100%; height:400px};
|
#map_canvas{width:100%; height:400px;}
|
||||||
|
#sound-att-table {width:100%; table-layout: fixed; word-break: break-word; border-collapse: collapse;}
|
||||||
|
#sound-att-table th{text-align:left;}
|
||||||
|
#sound-att-table .soundmap-att-left{width:60%; padding-right:6px}
|
||||||
|
#sound-att-table tr {border-bottom:1px solid #666;}
|
||||||
|
#sound-att-table td {padding: 3px 0;}
|
||||||
|
BIN
soundmap/img/datepicker_b.png
Normal file
After Width: | Height: | Size: 110 B |
BIN
soundmap/img/datepicker_bl.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
soundmap/img/datepicker_br.png
Normal file
After Width: | Height: | Size: 157 B |
BIN
soundmap/img/datepicker_l.png
Normal file
After Width: | Height: | Size: 116 B |
BIN
soundmap/img/datepicker_r.png
Normal file
After Width: | Height: | Size: 110 B |
BIN
soundmap/img/datepicker_t.png
Normal file
After Width: | Height: | Size: 113 B |
BIN
soundmap/img/datepicker_tl.png
Normal file
After Width: | Height: | Size: 169 B |
BIN
soundmap/img/datepicker_tr.png
Normal file
After Width: | Height: | Size: 179 B |
BIN
soundmap/img/field.png
Normal file
After Width: | Height: | Size: 767 B |
BIN
soundmap/img/pbar-ani.gif
Normal file
After Width: | Height: | Size: 297 KiB |
891
soundmap/js/jquery.datepicker.js
Normal file
@ -0,0 +1,891 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* Date picker
|
||||||
|
* Author: Stefan Petre www.eyecon.ro
|
||||||
|
*
|
||||||
|
* Dual licensed under the MIT and GPL licenses
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
(function ($) {
|
||||||
|
var DatePicker = function () {
|
||||||
|
var ids = {},
|
||||||
|
views = {
|
||||||
|
years: 'datepickerViewYears',
|
||||||
|
moths: 'datepickerViewMonths',
|
||||||
|
days: 'datepickerViewDays'
|
||||||
|
},
|
||||||
|
tpl = {
|
||||||
|
wrapper: '<div class="datepicker"><div class="datepickerBorderT" /><div class="datepickerBorderB" /><div class="datepickerBorderL" /><div class="datepickerBorderR" /><div class="datepickerBorderTL" /><div class="datepickerBorderTR" /><div class="datepickerBorderBL" /><div class="datepickerBorderBR" /><div class="datepickerContainer"><table cellspacing="0" cellpadding="0"><tbody><tr></tr></tbody></table></div></div>',
|
||||||
|
head: [
|
||||||
|
'<td>',
|
||||||
|
'<table cellspacing="0" cellpadding="0">',
|
||||||
|
'<thead>',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerGoPrev"><a href="#"><span><%=prev%></span></a></th>',
|
||||||
|
'<th colspan="6" class="datepickerMonth"><a href="#"><span></span></a></th>',
|
||||||
|
'<th class="datepickerGoNext"><a href="#"><span><%=next%></span></a></th>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr class="datepickerDoW">',
|
||||||
|
'<th><span><%=week%></span></th>',
|
||||||
|
'<th><span><%=day1%></span></th>',
|
||||||
|
'<th><span><%=day2%></span></th>',
|
||||||
|
'<th><span><%=day3%></span></th>',
|
||||||
|
'<th><span><%=day4%></span></th>',
|
||||||
|
'<th><span><%=day5%></span></th>',
|
||||||
|
'<th><span><%=day6%></span></th>',
|
||||||
|
'<th><span><%=day7%></span></th>',
|
||||||
|
'</tr>',
|
||||||
|
'</thead>',
|
||||||
|
'</table></td>'
|
||||||
|
],
|
||||||
|
space : '<td class="datepickerSpace"><div></div></td>',
|
||||||
|
days: [
|
||||||
|
'<tbody class="datepickerDays">',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerWeek"><a href="#"><span><%=weeks[0].week%></span></a></th>',
|
||||||
|
'<td class="<%=weeks[0].days[0].classname%>"><a href="#"><span><%=weeks[0].days[0].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[0].days[1].classname%>"><a href="#"><span><%=weeks[0].days[1].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[0].days[2].classname%>"><a href="#"><span><%=weeks[0].days[2].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[0].days[3].classname%>"><a href="#"><span><%=weeks[0].days[3].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[0].days[4].classname%>"><a href="#"><span><%=weeks[0].days[4].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[0].days[5].classname%>"><a href="#"><span><%=weeks[0].days[5].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[0].days[6].classname%>"><a href="#"><span><%=weeks[0].days[6].text%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerWeek"><a href="#"><span><%=weeks[1].week%></span></a></th>',
|
||||||
|
'<td class="<%=weeks[1].days[0].classname%>"><a href="#"><span><%=weeks[1].days[0].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[1].days[1].classname%>"><a href="#"><span><%=weeks[1].days[1].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[1].days[2].classname%>"><a href="#"><span><%=weeks[1].days[2].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[1].days[3].classname%>"><a href="#"><span><%=weeks[1].days[3].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[1].days[4].classname%>"><a href="#"><span><%=weeks[1].days[4].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[1].days[5].classname%>"><a href="#"><span><%=weeks[1].days[5].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[1].days[6].classname%>"><a href="#"><span><%=weeks[1].days[6].text%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerWeek"><a href="#"><span><%=weeks[2].week%></span></a></th>',
|
||||||
|
'<td class="<%=weeks[2].days[0].classname%>"><a href="#"><span><%=weeks[2].days[0].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[2].days[1].classname%>"><a href="#"><span><%=weeks[2].days[1].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[2].days[2].classname%>"><a href="#"><span><%=weeks[2].days[2].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[2].days[3].classname%>"><a href="#"><span><%=weeks[2].days[3].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[2].days[4].classname%>"><a href="#"><span><%=weeks[2].days[4].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[2].days[5].classname%>"><a href="#"><span><%=weeks[2].days[5].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[2].days[6].classname%>"><a href="#"><span><%=weeks[2].days[6].text%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerWeek"><a href="#"><span><%=weeks[3].week%></span></a></th>',
|
||||||
|
'<td class="<%=weeks[3].days[0].classname%>"><a href="#"><span><%=weeks[3].days[0].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[3].days[1].classname%>"><a href="#"><span><%=weeks[3].days[1].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[3].days[2].classname%>"><a href="#"><span><%=weeks[3].days[2].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[3].days[3].classname%>"><a href="#"><span><%=weeks[3].days[3].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[3].days[4].classname%>"><a href="#"><span><%=weeks[3].days[4].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[3].days[5].classname%>"><a href="#"><span><%=weeks[3].days[5].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[3].days[6].classname%>"><a href="#"><span><%=weeks[3].days[6].text%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerWeek"><a href="#"><span><%=weeks[4].week%></span></a></th>',
|
||||||
|
'<td class="<%=weeks[4].days[0].classname%>"><a href="#"><span><%=weeks[4].days[0].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[4].days[1].classname%>"><a href="#"><span><%=weeks[4].days[1].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[4].days[2].classname%>"><a href="#"><span><%=weeks[4].days[2].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[4].days[3].classname%>"><a href="#"><span><%=weeks[4].days[3].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[4].days[4].classname%>"><a href="#"><span><%=weeks[4].days[4].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[4].days[5].classname%>"><a href="#"><span><%=weeks[4].days[5].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[4].days[6].classname%>"><a href="#"><span><%=weeks[4].days[6].text%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<th class="datepickerWeek"><a href="#"><span><%=weeks[5].week%></span></a></th>',
|
||||||
|
'<td class="<%=weeks[5].days[0].classname%>"><a href="#"><span><%=weeks[5].days[0].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[5].days[1].classname%>"><a href="#"><span><%=weeks[5].days[1].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[5].days[2].classname%>"><a href="#"><span><%=weeks[5].days[2].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[5].days[3].classname%>"><a href="#"><span><%=weeks[5].days[3].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[5].days[4].classname%>"><a href="#"><span><%=weeks[5].days[4].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[5].days[5].classname%>"><a href="#"><span><%=weeks[5].days[5].text%></span></a></td>',
|
||||||
|
'<td class="<%=weeks[5].days[6].classname%>"><a href="#"><span><%=weeks[5].days[6].text%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'</tbody>'
|
||||||
|
],
|
||||||
|
months: [
|
||||||
|
'<tbody class="<%=className%>">',
|
||||||
|
'<tr>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[0]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[1]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[2]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[3]%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[4]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[5]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[6]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[7]%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'<tr>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[8]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[9]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[10]%></span></a></td>',
|
||||||
|
'<td colspan="2"><a href="#"><span><%=data[11]%></span></a></td>',
|
||||||
|
'</tr>',
|
||||||
|
'</tbody>'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
defaults = {
|
||||||
|
flat: false,
|
||||||
|
starts: 1,
|
||||||
|
prev: '◀',
|
||||||
|
next: '▶',
|
||||||
|
lastSel: false,
|
||||||
|
mode: 'single',
|
||||||
|
view: 'days',
|
||||||
|
calendars: 1,
|
||||||
|
format: 'Y-m-d',
|
||||||
|
position: 'bottom',
|
||||||
|
eventName: 'click',
|
||||||
|
onRender: function(){return {};},
|
||||||
|
onChange: function(){return true;},
|
||||||
|
onShow: function(){return true;},
|
||||||
|
onBeforeShow: function(){return true;},
|
||||||
|
onHide: function(){return true;},
|
||||||
|
locale: {
|
||||||
|
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
||||||
|
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||||
|
daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
|
||||||
|
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
||||||
|
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||||
|
weekMin: 'wk'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fill = function(el) {
|
||||||
|
var options = $(el).data('datepicker');
|
||||||
|
var cal = $(el);
|
||||||
|
var currentCal = Math.floor(options.calendars/2), date, data, dow, month, cnt = 0, week, days, indic, indic2, html, tblCal;
|
||||||
|
cal.find('td>table tbody').remove();
|
||||||
|
for (var i = 0; i < options.calendars; i++) {
|
||||||
|
date = new Date(options.current);
|
||||||
|
date.addMonths(-currentCal + i);
|
||||||
|
tblCal = cal.find('table').eq(i+1);
|
||||||
|
switch (tblCal[0].className) {
|
||||||
|
case 'datepickerViewDays':
|
||||||
|
dow = formatDate(date, 'B, Y');
|
||||||
|
break;
|
||||||
|
case 'datepickerViewMonths':
|
||||||
|
dow = date.getFullYear();
|
||||||
|
break;
|
||||||
|
case 'datepickerViewYears':
|
||||||
|
dow = (date.getFullYear()-6) + ' - ' + (date.getFullYear()+5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tblCal.find('thead tr:first th:eq(1) span').text(dow);
|
||||||
|
dow = date.getFullYear()-6;
|
||||||
|
data = {
|
||||||
|
data: [],
|
||||||
|
className: 'datepickerYears'
|
||||||
|
}
|
||||||
|
for ( var j = 0; j < 12; j++) {
|
||||||
|
data.data.push(dow + j);
|
||||||
|
}
|
||||||
|
html = tmpl(tpl.months.join(''), data);
|
||||||
|
date.setDate(1);
|
||||||
|
data = {weeks:[], test: 10};
|
||||||
|
month = date.getMonth();
|
||||||
|
var dow = (date.getDay() - options.starts) % 7;
|
||||||
|
date.addDays(-(dow + (dow < 0 ? 7 : 0)));
|
||||||
|
week = -1;
|
||||||
|
cnt = 0;
|
||||||
|
while (cnt < 42) {
|
||||||
|
indic = parseInt(cnt/7,10);
|
||||||
|
indic2 = cnt%7;
|
||||||
|
if (!data.weeks[indic]) {
|
||||||
|
week = date.getWeekNumber();
|
||||||
|
data.weeks[indic] = {
|
||||||
|
week: week,
|
||||||
|
days: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
data.weeks[indic].days[indic2] = {
|
||||||
|
text: date.getDate(),
|
||||||
|
classname: []
|
||||||
|
};
|
||||||
|
if (month != date.getMonth()) {
|
||||||
|
data.weeks[indic].days[indic2].classname.push('datepickerNotInMonth');
|
||||||
|
}
|
||||||
|
if (date.getDay() == 0) {
|
||||||
|
data.weeks[indic].days[indic2].classname.push('datepickerSunday');
|
||||||
|
}
|
||||||
|
if (date.getDay() == 6) {
|
||||||
|
data.weeks[indic].days[indic2].classname.push('datepickerSaturday');
|
||||||
|
}
|
||||||
|
var fromUser = options.onRender(date);
|
||||||
|
var val = date.valueOf();
|
||||||
|
if (fromUser.selected || options.date == val || $.inArray(val, options.date) > -1 || (options.mode == 'range' && val >= options.date[0] && val <= options.date[1])) {
|
||||||
|
data.weeks[indic].days[indic2].classname.push('datepickerSelected');
|
||||||
|
}
|
||||||
|
if (fromUser.disabled) {
|
||||||
|
data.weeks[indic].days[indic2].classname.push('datepickerDisabled');
|
||||||
|
}
|
||||||
|
if (fromUser.className) {
|
||||||
|
data.weeks[indic].days[indic2].classname.push(fromUser.className);
|
||||||
|
}
|
||||||
|
data.weeks[indic].days[indic2].classname = data.weeks[indic].days[indic2].classname.join(' ');
|
||||||
|
cnt++;
|
||||||
|
date.addDays(1);
|
||||||
|
}
|
||||||
|
html = tmpl(tpl.days.join(''), data) + html;
|
||||||
|
data = {
|
||||||
|
data: options.locale.monthsShort,
|
||||||
|
className: 'datepickerMonths'
|
||||||
|
};
|
||||||
|
html = tmpl(tpl.months.join(''), data) + html;
|
||||||
|
tblCal.append(html);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parseDate = function (date, format) {
|
||||||
|
if (date.constructor == Date) {
|
||||||
|
return new Date(date);
|
||||||
|
}
|
||||||
|
var parts = date.split(/\W+/);
|
||||||
|
var against = format.split(/\W+/), d, m, y, h, min, now = new Date();
|
||||||
|
for (var i = 0; i < parts.length; i++) {
|
||||||
|
switch (against[i]) {
|
||||||
|
case 'd':
|
||||||
|
case 'e':
|
||||||
|
d = parseInt(parts[i],10);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
m = parseInt(parts[i], 10)-1;
|
||||||
|
break;
|
||||||
|
case 'Y':
|
||||||
|
case 'y':
|
||||||
|
y = parseInt(parts[i], 10);
|
||||||
|
y += y > 100 ? 0 : (y < 29 ? 2000 : 1900);
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
case 'I':
|
||||||
|
case 'k':
|
||||||
|
case 'l':
|
||||||
|
h = parseInt(parts[i], 10);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
if (/pm/i.test(parts[i]) && h < 12) {
|
||||||
|
h += 12;
|
||||||
|
} else if (/am/i.test(parts[i]) && h >= 12) {
|
||||||
|
h -= 12;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
min = parseInt(parts[i], 10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Date(
|
||||||
|
y === undefined ? now.getFullYear() : y,
|
||||||
|
m === undefined ? now.getMonth() : m,
|
||||||
|
d === undefined ? now.getDate() : d,
|
||||||
|
h === undefined ? now.getHours() : h,
|
||||||
|
min === undefined ? now.getMinutes() : min,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
},
|
||||||
|
formatDate = function(date, format) {
|
||||||
|
var m = date.getMonth();
|
||||||
|
var d = date.getDate();
|
||||||
|
var y = date.getFullYear();
|
||||||
|
var wn = date.getWeekNumber();
|
||||||
|
var w = date.getDay();
|
||||||
|
var s = {};
|
||||||
|
var hr = date.getHours();
|
||||||
|
var pm = (hr >= 12);
|
||||||
|
var ir = (pm) ? (hr - 12) : hr;
|
||||||
|
var dy = date.getDayOfYear();
|
||||||
|
if (ir == 0) {
|
||||||
|
ir = 12;
|
||||||
|
}
|
||||||
|
var min = date.getMinutes();
|
||||||
|
var sec = date.getSeconds();
|
||||||
|
var parts = format.split(''), part;
|
||||||
|
for ( var i = 0; i < parts.length; i++ ) {
|
||||||
|
part = parts[i];
|
||||||
|
switch (parts[i]) {
|
||||||
|
case 'a':
|
||||||
|
part = date.getDayName();
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
part = date.getDayName(true);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
part = date.getMonthName();
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
part = date.getMonthName(true);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
part = 1 + Math.floor(y / 100);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
part = (d < 10) ? ("0" + d) : d;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
part = d;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
part = (hr < 10) ? ("0" + hr) : hr;
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
part = (ir < 10) ? ("0" + ir) : ir;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
part = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
part = hr;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
part = ir;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
part = (m < 9) ? ("0" + (1+m)) : (1+m);
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
part = (min < 10) ? ("0" + min) : min;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
part = pm ? "PM" : "AM";
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
part = Math.floor(date.getTime() / 1000);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
part = (sec < 10) ? ("0" + sec) : sec;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
part = w + 1;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
part = w;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
part = ('' + y).substr(2, 2);
|
||||||
|
break;
|
||||||
|
case 'Y':
|
||||||
|
part = y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parts[i] = part;
|
||||||
|
}
|
||||||
|
return parts.join('');
|
||||||
|
},
|
||||||
|
extendDate = function(options) {
|
||||||
|
if (Date.prototype.tempDate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Date.prototype.tempDate = null;
|
||||||
|
Date.prototype.months = options.months;
|
||||||
|
Date.prototype.monthsShort = options.monthsShort;
|
||||||
|
Date.prototype.days = options.days;
|
||||||
|
Date.prototype.daysShort = options.daysShort;
|
||||||
|
Date.prototype.getMonthName = function(fullName) {
|
||||||
|
return this[fullName ? 'months' : 'monthsShort'][this.getMonth()];
|
||||||
|
};
|
||||||
|
Date.prototype.getDayName = function(fullName) {
|
||||||
|
return this[fullName ? 'days' : 'daysShort'][this.getDay()];
|
||||||
|
};
|
||||||
|
Date.prototype.addDays = function (n) {
|
||||||
|
this.setDate(this.getDate() + n);
|
||||||
|
this.tempDate = this.getDate();
|
||||||
|
};
|
||||||
|
Date.prototype.addMonths = function (n) {
|
||||||
|
if (this.tempDate == null) {
|
||||||
|
this.tempDate = this.getDate();
|
||||||
|
}
|
||||||
|
this.setDate(1);
|
||||||
|
this.setMonth(this.getMonth() + n);
|
||||||
|
this.setDate(Math.min(this.tempDate, this.getMaxDays()));
|
||||||
|
};
|
||||||
|
Date.prototype.addYears = function (n) {
|
||||||
|
if (this.tempDate == null) {
|
||||||
|
this.tempDate = this.getDate();
|
||||||
|
}
|
||||||
|
this.setDate(1);
|
||||||
|
this.setFullYear(this.getFullYear() + n);
|
||||||
|
this.setDate(Math.min(this.tempDate, this.getMaxDays()));
|
||||||
|
};
|
||||||
|
Date.prototype.getMaxDays = function() {
|
||||||
|
var tmpDate = new Date(Date.parse(this)),
|
||||||
|
d = 28, m;
|
||||||
|
m = tmpDate.getMonth();
|
||||||
|
d = 28;
|
||||||
|
while (tmpDate.getMonth() == m) {
|
||||||
|
d ++;
|
||||||
|
tmpDate.setDate(d);
|
||||||
|
}
|
||||||
|
return d - 1;
|
||||||
|
};
|
||||||
|
Date.prototype.getFirstDay = function() {
|
||||||
|
var tmpDate = new Date(Date.parse(this));
|
||||||
|
tmpDate.setDate(1);
|
||||||
|
return tmpDate.getDay();
|
||||||
|
};
|
||||||
|
Date.prototype.getWeekNumber = function() {
|
||||||
|
var tempDate = new Date(this);
|
||||||
|
tempDate.setDate(tempDate.getDate() - (tempDate.getDay() + 6) % 7 + 3);
|
||||||
|
var dms = tempDate.valueOf();
|
||||||
|
tempDate.setMonth(0);
|
||||||
|
tempDate.setDate(4);
|
||||||
|
return Math.round((dms - tempDate.valueOf()) / (604800000)) + 1;
|
||||||
|
};
|
||||||
|
Date.prototype.getDayOfYear = function() {
|
||||||
|
var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
|
||||||
|
var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
|
||||||
|
var time = now - then;
|
||||||
|
return Math.floor(time / 24*60*60*1000);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
layout = function (el) {
|
||||||
|
var options = $(el).data('datepicker');
|
||||||
|
var cal = $('#' + options.id);
|
||||||
|
if (!options.extraHeight) {
|
||||||
|
var divs = $(el).find('div');
|
||||||
|
options.extraHeight = divs.get(0).offsetHeight + divs.get(1).offsetHeight;
|
||||||
|
options.extraWidth = divs.get(2).offsetWidth + divs.get(3).offsetWidth;
|
||||||
|
}
|
||||||
|
var tbl = cal.find('table:first').get(0);
|
||||||
|
var width = tbl.offsetWidth;
|
||||||
|
var height = tbl.offsetHeight;
|
||||||
|
cal.css({
|
||||||
|
width: width + options.extraWidth + 'px',
|
||||||
|
height: height + options.extraHeight + 'px'
|
||||||
|
}).find('div.datepickerContainer').css({
|
||||||
|
width: width + 'px',
|
||||||
|
height: height + 'px'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
click = function(ev) {
|
||||||
|
if ($(ev.target).is('span')) {
|
||||||
|
ev.target = ev.target.parentNode;
|
||||||
|
}
|
||||||
|
var el = $(ev.target);
|
||||||
|
if (el.is('a')) {
|
||||||
|
ev.target.blur();
|
||||||
|
if (el.hasClass('datepickerDisabled')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var options = $(this).data('datepicker');
|
||||||
|
var parentEl = el.parent();
|
||||||
|
var tblEl = parentEl.parent().parent().parent();
|
||||||
|
var tblIndex = $('table', this).index(tblEl.get(0)) - 1;
|
||||||
|
var tmp = new Date(options.current);
|
||||||
|
var changed = false;
|
||||||
|
var fillIt = false;
|
||||||
|
if (parentEl.is('th')) {
|
||||||
|
if (parentEl.hasClass('datepickerWeek') && options.mode == 'range' && !parentEl.next().hasClass('datepickerDisabled')) {
|
||||||
|
var val = parseInt(parentEl.next().text(), 10);
|
||||||
|
tmp.addMonths(tblIndex - Math.floor(options.calendars/2));
|
||||||
|
if (parentEl.next().hasClass('datepickerNotInMonth')) {
|
||||||
|
tmp.addMonths(val > 15 ? -1 : 1);
|
||||||
|
}
|
||||||
|
tmp.setDate(val);
|
||||||
|
options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
|
||||||
|
tmp.setHours(23,59,59,0);
|
||||||
|
tmp.addDays(6);
|
||||||
|
options.date[1] = tmp.valueOf();
|
||||||
|
fillIt = true;
|
||||||
|
changed = true;
|
||||||
|
options.lastSel = false;
|
||||||
|
} else if (parentEl.hasClass('datepickerMonth')) {
|
||||||
|
tmp.addMonths(tblIndex - Math.floor(options.calendars/2));
|
||||||
|
switch (tblEl.get(0).className) {
|
||||||
|
case 'datepickerViewDays':
|
||||||
|
tblEl.get(0).className = 'datepickerViewMonths';
|
||||||
|
el.find('span').text(tmp.getFullYear());
|
||||||
|
break;
|
||||||
|
case 'datepickerViewMonths':
|
||||||
|
tblEl.get(0).className = 'datepickerViewYears';
|
||||||
|
el.find('span').text((tmp.getFullYear()-6) + ' - ' + (tmp.getFullYear()+5));
|
||||||
|
break;
|
||||||
|
case 'datepickerViewYears':
|
||||||
|
tblEl.get(0).className = 'datepickerViewDays';
|
||||||
|
el.find('span').text(formatDate(tmp, 'B, Y'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (parentEl.parent().parent().is('thead')) {
|
||||||
|
switch (tblEl.get(0).className) {
|
||||||
|
case 'datepickerViewDays':
|
||||||
|
options.current.addMonths(parentEl.hasClass('datepickerGoPrev') ? -1 : 1);
|
||||||
|
break;
|
||||||
|
case 'datepickerViewMonths':
|
||||||
|
options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -1 : 1);
|
||||||
|
break;
|
||||||
|
case 'datepickerViewYears':
|
||||||
|
options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -12 : 12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fillIt = true;
|
||||||
|
}
|
||||||
|
} else if (parentEl.is('td') && !parentEl.hasClass('datepickerDisabled')) {
|
||||||
|
switch (tblEl.get(0).className) {
|
||||||
|
case 'datepickerViewMonths':
|
||||||
|
options.current.setMonth(tblEl.find('tbody.datepickerMonths td').index(parentEl));
|
||||||
|
options.current.setFullYear(parseInt(tblEl.find('thead th.datepickerMonth span').text(), 10));
|
||||||
|
options.current.addMonths(Math.floor(options.calendars/2) - tblIndex);
|
||||||
|
tblEl.get(0).className = 'datepickerViewDays';
|
||||||
|
break;
|
||||||
|
case 'datepickerViewYears':
|
||||||
|
options.current.setFullYear(parseInt(el.text(), 10));
|
||||||
|
tblEl.get(0).className = 'datepickerViewMonths';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var val = parseInt(el.text(), 10);
|
||||||
|
tmp.addMonths(tblIndex - Math.floor(options.calendars/2));
|
||||||
|
if (parentEl.hasClass('datepickerNotInMonth')) {
|
||||||
|
tmp.addMonths(val > 15 ? -1 : 1);
|
||||||
|
}
|
||||||
|
tmp.setDate(val);
|
||||||
|
switch (options.mode) {
|
||||||
|
case 'multiple':
|
||||||
|
val = (tmp.setHours(0,0,0,0)).valueOf();
|
||||||
|
if ($.inArray(val, options.date) > -1) {
|
||||||
|
$.each(options.date, function(nr, dat){
|
||||||
|
if (dat == val) {
|
||||||
|
options.date.splice(nr,1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
options.date.push(val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'range':
|
||||||
|
if (!options.lastSel) {
|
||||||
|
options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();
|
||||||
|
}
|
||||||
|
val = (tmp.setHours(23,59,59,0)).valueOf();
|
||||||
|
if (val < options.date[0]) {
|
||||||
|
options.date[1] = options.date[0] + 86399000;
|
||||||
|
options.date[0] = val - 86399000;
|
||||||
|
} else {
|
||||||
|
options.date[1] = val;
|
||||||
|
}
|
||||||
|
options.lastSel = !options.lastSel;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
options.date = tmp.valueOf();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fillIt = true;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (fillIt) {
|
||||||
|
fill(this);
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
options.onChange.apply(this, prepareDate(options));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
prepareDate = function (options) {
|
||||||
|
var tmp;
|
||||||
|
if (options.mode == 'single') {
|
||||||
|
tmp = new Date(options.date);
|
||||||
|
return [formatDate(tmp, options.format), tmp, options.el];
|
||||||
|
} else {
|
||||||
|
tmp = [[],[], options.el];
|
||||||
|
$.each(options.date, function(nr, val){
|
||||||
|
var date = new Date(val);
|
||||||
|
tmp[0].push(formatDate(date, options.format));
|
||||||
|
tmp[1].push(date);
|
||||||
|
});
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getViewport = function () {
|
||||||
|
var m = document.compatMode == 'CSS1Compat';
|
||||||
|
return {
|
||||||
|
l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
|
||||||
|
t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
|
||||||
|
w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
|
||||||
|
h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
isChildOf = function(parentEl, el, container) {
|
||||||
|
if (parentEl == el) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (parentEl.contains) {
|
||||||
|
return parentEl.contains(el);
|
||||||
|
}
|
||||||
|
if ( parentEl.compareDocumentPosition ) {
|
||||||
|
return !!(parentEl.compareDocumentPosition(el) & 16);
|
||||||
|
}
|
||||||
|
var prEl = el.parentNode;
|
||||||
|
while(prEl && prEl != container) {
|
||||||
|
if (prEl == parentEl)
|
||||||
|
return true;
|
||||||
|
prEl = prEl.parentNode;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
show = function (ev) {
|
||||||
|
var cal = $('#' + $(this).data('datepickerId'));
|
||||||
|
if (!cal.is(':visible')) {
|
||||||
|
var calEl = cal.get(0);
|
||||||
|
fill(calEl);
|
||||||
|
var options = cal.data('datepicker');
|
||||||
|
options.onBeforeShow.apply(this, [cal.get(0)]);
|
||||||
|
var pos = $(this).offset();
|
||||||
|
var viewPort = getViewport();
|
||||||
|
var top = pos.top;
|
||||||
|
var left = pos.left;
|
||||||
|
var oldDisplay = $.curCSS(calEl, 'display');
|
||||||
|
cal.css({
|
||||||
|
visibility: 'hidden',
|
||||||
|
display: 'block'
|
||||||
|
});
|
||||||
|
layout(calEl);
|
||||||
|
switch (options.position){
|
||||||
|
case 'top':
|
||||||
|
top -= calEl.offsetHeight;
|
||||||
|
break;
|
||||||
|
case 'left':
|
||||||
|
left -= calEl.offsetWidth;
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
left += this.offsetWidth;
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
top += this.offsetHeight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (top + calEl.offsetHeight > viewPort.t + viewPort.h) {
|
||||||
|
top = pos.top - calEl.offsetHeight;
|
||||||
|
}
|
||||||
|
if (top < viewPort.t) {
|
||||||
|
top = pos.top + this.offsetHeight + calEl.offsetHeight;
|
||||||
|
}
|
||||||
|
if (left + calEl.offsetWidth > viewPort.l + viewPort.w) {
|
||||||
|
left = pos.left - calEl.offsetWidth;
|
||||||
|
}
|
||||||
|
if (left < viewPort.l) {
|
||||||
|
left = pos.left + this.offsetWidth
|
||||||
|
}
|
||||||
|
cal.css({
|
||||||
|
visibility: 'visible',
|
||||||
|
display: 'block',
|
||||||
|
top: top + 'px',
|
||||||
|
left: left + 'px'
|
||||||
|
});
|
||||||
|
if (options.onShow.apply(this, [cal.get(0)]) != false) {
|
||||||
|
cal.show();
|
||||||
|
}
|
||||||
|
$(document).bind('mousedown', {cal: cal, trigger: this}, hide);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
hide = function (ev) {
|
||||||
|
if (ev.target != ev.data.trigger && !isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
|
||||||
|
if (ev.data.cal.data('datepicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
|
||||||
|
ev.data.cal.hide();
|
||||||
|
}
|
||||||
|
$(document).unbind('mousedown', hide);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
init: function(options){
|
||||||
|
options = $.extend({}, defaults, options||{});
|
||||||
|
extendDate(options.locale);
|
||||||
|
options.calendars = Math.max(1, parseInt(options.calendars,10)||1);
|
||||||
|
options.mode = /single|multiple|range/.test(options.mode) ? options.mode : 'single';
|
||||||
|
return this.each(function(){
|
||||||
|
if (!$(this).data('datepicker')) {
|
||||||
|
options.el = this;
|
||||||
|
if (options.date.constructor == String) {
|
||||||
|
options.date = parseDate(options.date, options.format);
|
||||||
|
options.date.setHours(0,0,0,0);
|
||||||
|
}
|
||||||
|
if (options.mode != 'single') {
|
||||||
|
if (options.date.constructor != Array) {
|
||||||
|
options.date = [options.date.valueOf()];
|
||||||
|
if (options.mode == 'range') {
|
||||||
|
options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < options.date.length; i++) {
|
||||||
|
options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf();
|
||||||
|
}
|
||||||
|
if (options.mode == 'range') {
|
||||||
|
options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
options.date = options.date.valueOf();
|
||||||
|
}
|
||||||
|
if (!options.current) {
|
||||||
|
options.current = new Date();
|
||||||
|
} else {
|
||||||
|
options.current = parseDate(options.current, options.format);
|
||||||
|
}
|
||||||
|
options.current.setDate(1);
|
||||||
|
options.current.setHours(0,0,0,0);
|
||||||
|
var id = 'datepicker_' + parseInt(Math.random() * 1000), cnt;
|
||||||
|
options.id = id;
|
||||||
|
$(this).data('datepickerId', options.id);
|
||||||
|
var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options);
|
||||||
|
if (options.className) {
|
||||||
|
cal.addClass(options.className);
|
||||||
|
}
|
||||||
|
var html = '';
|
||||||
|
for (var i = 0; i < options.calendars; i++) {
|
||||||
|
cnt = options.starts;
|
||||||
|
if (i > 0) {
|
||||||
|
html += tpl.space;
|
||||||
|
}
|
||||||
|
html += tmpl(tpl.head.join(''), {
|
||||||
|
week: options.locale.weekMin,
|
||||||
|
prev: options.prev,
|
||||||
|
next: options.next,
|
||||||
|
day1: options.locale.daysMin[(cnt++)%7],
|
||||||
|
day2: options.locale.daysMin[(cnt++)%7],
|
||||||
|
day3: options.locale.daysMin[(cnt++)%7],
|
||||||
|
day4: options.locale.daysMin[(cnt++)%7],
|
||||||
|
day5: options.locale.daysMin[(cnt++)%7],
|
||||||
|
day6: options.locale.daysMin[(cnt++)%7],
|
||||||
|
day7: options.locale.daysMin[(cnt++)%7]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cal
|
||||||
|
.find('tr:first').append(html)
|
||||||
|
.find('table').addClass(views[options.view]);
|
||||||
|
fill(cal.get(0));
|
||||||
|
if (options.flat) {
|
||||||
|
cal.appendTo(this).show().css('position', 'relative');
|
||||||
|
layout(cal.get(0));
|
||||||
|
} else {
|
||||||
|
cal.appendTo(document.body);
|
||||||
|
$(this).bind(options.eventName, show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showPicker: function() {
|
||||||
|
return this.each( function () {
|
||||||
|
if ($(this).data('datepickerId')) {
|
||||||
|
show.apply(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
hidePicker: function() {
|
||||||
|
return this.each( function () {
|
||||||
|
if ($(this).data('datepickerId')) {
|
||||||
|
$('#' + $(this).data('datepickerId')).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setDate: function(date, shiftTo){
|
||||||
|
return this.each(function(){
|
||||||
|
if ($(this).data('datepickerId')) {
|
||||||
|
var cal = $('#' + $(this).data('datepickerId'));
|
||||||
|
var options = cal.data('datepicker');
|
||||||
|
options.date = date;
|
||||||
|
if (options.date.constructor == String) {
|
||||||
|
options.date = parseDate(options.date, options.format);
|
||||||
|
options.date.setHours(0,0,0,0);
|
||||||
|
}
|
||||||
|
if (options.mode != 'single') {
|
||||||
|
if (options.date.constructor != Array) {
|
||||||
|
options.date = [options.date.valueOf()];
|
||||||
|
if (options.mode == 'range') {
|
||||||
|
options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < options.date.length; i++) {
|
||||||
|
options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf();
|
||||||
|
}
|
||||||
|
if (options.mode == 'range') {
|
||||||
|
options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
options.date = options.date.valueOf();
|
||||||
|
}
|
||||||
|
if (shiftTo) {
|
||||||
|
options.current = new Date (options.mode != 'single' ? options.date[0] : options.date);
|
||||||
|
}
|
||||||
|
fill(cal.get(0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getDate: function(formated) {
|
||||||
|
if (this.size() > 0) {
|
||||||
|
return prepareDate($('#' + $(this).data('datepickerId')).data('datepicker'))[formated ? 0 : 1];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clear: function(){
|
||||||
|
return this.each(function(){
|
||||||
|
if ($(this).data('datepickerId')) {
|
||||||
|
var cal = $('#' + $(this).data('datepickerId'));
|
||||||
|
var options = cal.data('datepicker');
|
||||||
|
if (options.mode != 'single') {
|
||||||
|
options.date = [];
|
||||||
|
fill(cal.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fixLayout: function(){
|
||||||
|
return this.each(function(){
|
||||||
|
if ($(this).data('datepickerId')) {
|
||||||
|
var cal = $('#' + $(this).data('datepickerId'));
|
||||||
|
var options = cal.data('datepicker');
|
||||||
|
if (options.flat) {
|
||||||
|
layout(cal.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
$.fn.extend({
|
||||||
|
DatePicker: DatePicker.init,
|
||||||
|
DatePickerHide: DatePicker.hidePicker,
|
||||||
|
DatePickerShow: DatePicker.showPicker,
|
||||||
|
DatePickerSetDate: DatePicker.setDate,
|
||||||
|
DatePickerGetDate: DatePicker.getDate,
|
||||||
|
DatePickerClear: DatePicker.clear,
|
||||||
|
DatePickerLayout: DatePicker.fixLayout
|
||||||
|
});
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var cache = {};
|
||||||
|
|
||||||
|
this.tmpl = function tmpl(str, data){
|
||||||
|
// Figure out if we're getting a template, or if we need to
|
||||||
|
// load the template - and be sure to cache the result.
|
||||||
|
var fn = !/\W/.test(str) ?
|
||||||
|
cache[str] = cache[str] ||
|
||||||
|
tmpl(document.getElementById(str).innerHTML) :
|
||||||
|
|
||||||
|
// Generate a reusable function that will serve as a template
|
||||||
|
// generator (and which will be cached).
|
||||||
|
new Function("obj",
|
||||||
|
"var p=[],print=function(){p.push.apply(p,arguments);};" +
|
||||||
|
|
||||||
|
// Introduce the data as local variables using with(){}
|
||||||
|
"with(obj){p.push('" +
|
||||||
|
|
||||||
|
// Convert the template into pure JavaScript
|
||||||
|
str
|
||||||
|
.replace(/[\r\t\n]/g, " ")
|
||||||
|
.split("<%").join("\t")
|
||||||
|
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
|
||||||
|
.replace(/\t=(.*?)%>/g, "',$1,'")
|
||||||
|
.split("\t").join("');")
|
||||||
|
.split("%>").join("p.push('")
|
||||||
|
.split("\r").join("\\'")
|
||||||
|
+ "');}return p.join('');");
|
||||||
|
|
||||||
|
// Provide some basic currying to the user
|
||||||
|
return data ? fn( data ) : fn;
|
||||||
|
};
|
||||||
|
})();
|
@ -1,229 +0,0 @@
|
|||||||
/*!
|
|
||||||
* jQuery UI Google Maps 2.0
|
|
||||||
* http://code.google.com/p/jquery-ui-map/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010-2011 Johan Säll Larsson
|
|
||||||
*
|
|
||||||
* Microdatajs
|
|
||||||
* http://gitorious.org/microdatajs/microdatajs
|
|
||||||
* Copyright (c) 2009-2011 Philip Jägenstedt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Depends:
|
|
||||||
* jquery.ui.core.js
|
|
||||||
* jquery.ui.widget.js
|
|
||||||
* jquery.ui.map.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
( function($) {
|
|
||||||
|
|
||||||
jQuery.fn.extend({
|
|
||||||
|
|
||||||
items: getItems,
|
|
||||||
itemScope: itemScope,
|
|
||||||
itemType: itemType,
|
|
||||||
itemId: itemId,
|
|
||||||
itemProp: tokenList('itemprop'),
|
|
||||||
itemRef: tokenList('itemref'),
|
|
||||||
itemValue: itemValue
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function itemValue() {
|
|
||||||
var elm = this.get(0);
|
|
||||||
if (this.attr('itemprop') === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (this.itemScope()) {
|
|
||||||
return elm;
|
|
||||||
}
|
|
||||||
switch (elm.tagName.toUpperCase()) {
|
|
||||||
case 'META':
|
|
||||||
return this.attr('content') || '';
|
|
||||||
case 'AUDIO':
|
|
||||||
case 'EMBED':
|
|
||||||
case 'IFRAME':
|
|
||||||
case 'IMG':
|
|
||||||
case 'SOURCE':
|
|
||||||
case 'VIDEO':
|
|
||||||
return resolve(this.attr('src'));
|
|
||||||
case 'A':
|
|
||||||
case 'AREA':
|
|
||||||
case 'LINK':
|
|
||||||
return resolve(this.attr('href'));
|
|
||||||
case 'OBJECT':
|
|
||||||
return resolve(this.attr('data'));
|
|
||||||
case 'TIME':
|
|
||||||
var datetime = this.attr('datetime');
|
|
||||||
if (!(datetime === undefined))
|
|
||||||
return datetime;
|
|
||||||
default:
|
|
||||||
return this.text();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function itemId() {
|
|
||||||
return resolve(this.attr('itemid'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function itemScope() {
|
|
||||||
return this.attr('itemscope') != undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function itemType() {
|
|
||||||
return this.attr('itemtype') || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function splitTokens(s) {
|
|
||||||
if (s && /\S/.test(s))
|
|
||||||
return s.replace(/^\s+|\s+$/g,'').split(/\s+/);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolve(url) {
|
|
||||||
if (!url)
|
|
||||||
return '';
|
|
||||||
var img = document.createElement('img');
|
|
||||||
img.setAttribute('src', url);
|
|
||||||
return img.src;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItems(types) {
|
|
||||||
var selector = jQuery.map(splitTokens(types), function(t) {
|
|
||||||
return '[itemtype~="'+t.replace(/"/g, '\\"')+'"]';
|
|
||||||
}).join(',') || '*';
|
|
||||||
// filter results to only match top-level items
|
|
||||||
// because [attr] selector doesn't work in IE we have to
|
|
||||||
// filter the elements. http://dev.jquery.com/ticket/5637
|
|
||||||
return jQuery(selector, this).filter(function() {
|
|
||||||
return (this.getAttribute('itemscope') != null && this.getAttribute('itemprop') == null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function tokenList(attr) {
|
|
||||||
return function() {
|
|
||||||
var tokens = [];
|
|
||||||
jQuery.each(splitTokens(this.attr(attr)), function(i, token) {
|
|
||||||
if (jQuery.inArray(token, tokens) == -1)
|
|
||||||
tokens.push(token);
|
|
||||||
});
|
|
||||||
return jQuery(tokens);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItem($item, list, key, latlngs) {
|
|
||||||
|
|
||||||
var result = {};
|
|
||||||
|
|
||||||
if ( $item.itemType() ) {
|
|
||||||
result.type = $item.itemType();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $item.itemId() ) {
|
|
||||||
result.id = $item.itemId();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.properties = {};
|
|
||||||
result.list = list;
|
|
||||||
|
|
||||||
$item.children().each(function() {
|
|
||||||
|
|
||||||
var $elem = jQuery(this);
|
|
||||||
|
|
||||||
var value;
|
|
||||||
|
|
||||||
if ( $elem.itemScope() ) {
|
|
||||||
value = getItem($elem, list, key, latlngs);
|
|
||||||
} else {
|
|
||||||
value = $elem.itemValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
$elem.itemProp().each(function() {
|
|
||||||
|
|
||||||
if (!result.properties[this]) {
|
|
||||||
result.properties[this] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( typeof value != "object" ) {
|
|
||||||
result.list[this] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.properties[this].push(value);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( latlngs.length > 0 ) {
|
|
||||||
var t = $elem.itemType();
|
|
||||||
if ( typeof t == "string" && t.toLowerCase().indexOf('geo') > -1 ) {
|
|
||||||
result.properties['geo'][0].properties = latlngs[key];
|
|
||||||
result.list['geo'] = new google.maps.LatLng(latlngs[key].latitude[0],latlngs[key].longitude[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMetaTag() {
|
|
||||||
var latlng = [];
|
|
||||||
if ( $.browser.mozilla ) {
|
|
||||||
var lats = [];
|
|
||||||
var lngs = [];
|
|
||||||
var metas = document.getElementsByTagName('meta');
|
|
||||||
for ( i = 0; i < metas.length; i++ ) {
|
|
||||||
var meta = $(metas[i]);
|
|
||||||
if ( meta.attr('itemprop') == 'latitude' ) {
|
|
||||||
lats.push(meta.attr('content'));
|
|
||||||
}
|
|
||||||
if ( meta.attr('itemprop') == 'longitude' ) {
|
|
||||||
lngs.push(meta.attr('content'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( i = 0; i < lats.length; i++ ) {
|
|
||||||
latlng.push({ 'latitude': [lats[i]], 'longitude': [lngs[i]] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return latlng;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.extend($.ui.gmap, {
|
|
||||||
|
|
||||||
version: '1.0',
|
|
||||||
|
|
||||||
microdata: function(ns, callback) {
|
|
||||||
|
|
||||||
// Mozilla/Firefox adds meta tags in header
|
|
||||||
var latlngs = getMetaTag();
|
|
||||||
var items = jQuery(document).items(ns);
|
|
||||||
|
|
||||||
items.each(function(i, value) {
|
|
||||||
var item = $(value);
|
|
||||||
if (item.itemScope()) {
|
|
||||||
$.ui.gmap._trigger(callback, i, item, getItem(item, [], i, latlngs));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
} (jQuery) );
|
|
34
soundmap/js/jquery.ui.gmap.microdata.min.js
vendored
@ -1,34 +0,0 @@
|
|||||||
/*!
|
|
||||||
* jQuery UI Google Maps 2.0
|
|
||||||
* http://code.google.com/p/jquery-ui-map/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010-2011 Johan Säll Larsson
|
|
||||||
*
|
|
||||||
* Microdatajs
|
|
||||||
* http://gitorious.org/microdatajs/microdatajs
|
|
||||||
* Copyright (c) 2009-2011 Philip Jägenstedt
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Depends:
|
|
||||||
* jquery.ui.core.js
|
|
||||||
* jquery.ui.widget.js
|
|
||||||
* jquery.ui.map.js
|
|
||||||
*/
|
|
||||||
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(4($){b.1l.16({z:15,e:e,j:j,o:o,U:I(\'m\'),1m:I(\'1n\'),x:x});4 x(){5 D=3.1k(0);6(3.7(\'m\')===T){2 J}6(3.e()){2 D}1j(D.1f.1g()){9\'1h\':2 3.7(\'N\')||\'\';9\'1i\':9\'1o\':9\'1p\':9\'1v\':9\'1w\':9\'1x\':2 p(3.7(\'E\'));9\'A\':9\'1e\':9\'1t\':2 p(3.7(\'1q\'));9\'1r\':2 p(3.7(\'1s\'));9\'1y\':5 v=3.7(\'v\');6(!(v===T))2 v;1d:2 3.1c()}}4 o(){2 p(3.7(\'1b\'))}4 e(){2 3.7(\'W\')!=T}4 j(){2 3.7(\'13\')||\'\'}4 C(s){6(s&&/\\S/.1a(s))2 s.17(/^\\s+|\\s+$/g,\'\').1u(/\\s+/);2[]}4 p(K){6(!K)2\'\';5 r=F.1Q(\'r\');r.1O(\'E\',K);2 r.E}4 15(14){5 19=b.1N(C(14),4(t){2\'[13~="\'+t.17(/"/g,\'\\\\"\')+\'"]\'}).1S(\',\')||\'*\';2 b(19,3).1z(4(){2(3.Z(\'W\')!=J&&3.Z(\'m\')==J)})}4 I(7){2 4(){5 u=[];b.y(C(3.7(7)),4(i,H){6(b.1W(H,u)==-1)u.n(H)});2 b(u)}}4 B($a,f,q,d){5 8={};6($a.j()){8.1T=$a.j()}6($a.o()){8.1U=$a.o()}8.k={};8.f=f;$a.1L().y(4(){5 $l=b(3);5 c;6($l.e()){c=B($l,f,q,d)}1K{c=$l.x()}$l.U().y(4(){6(!8.k[3]){8.k[3]=[]}6(11 c!="1D"){8.f[3]=c}8.k[3].n(c)});6(d.M>0){5 t=$l.j();6(11 t=="1B"&&t.1A().1E(\'L\')>-1){8.k[\'L\'][0].k=d[q];8.f[\'L\']=1J 1I.1H.1G(d[q].R[0],d[q].G[0])}}});2 8}4 12(){5 O=[];6($.1C.1V){5 w=[];5 P=[];5 Q=F.1R(\'h\');V(i=0;i<Q.M;i++){5 h=$(Q[i]);6(h.7(\'m\')==\'R\'){w.n(h.7(\'N\'))}6(h.7(\'m\')==\'G\'){P.n(h.7(\'N\'))}}V(i=0;i<w.M;i++){O.n({\'R\':[w[i]],\'G\':[P[i]]})}}2 O}$.16($.Y.10,{1P:\'1.0\',1F:4(X,18){5 d=12();5 z=b(F).z(X);z.y(4(i,c){5 a=$(c);6(a.e()){$.Y.10.1M(18,i,a,B(a,[],i,d))}})}})}(b));',62,121,'||return|this|function|var|if|attr|result|case|item|jQuery|value|latlngs|itemScope|list||meta||itemType|properties|elem|itemprop|push|itemId|resolve|key|img|||tokens|datetime|lats|itemValue|each|items||getItem|splitTokens|elm|src|document|longitude|token|tokenList|null|url|geo|length|content|latlng|lngs|metas|latitude||undefined|itemProp|for|itemscope|ns|ui|getAttribute|gmap|typeof|getMetaTag|itemtype|types|getItems|extend|replace|callback|selector|test|itemid|text|default|AREA|tagName|toUpperCase|META|AUDIO|switch|get|fn|itemRef|itemref|EMBED|IFRAME|href|OBJECT|data|LINK|split|IMG|SOURCE|VIDEO|TIME|filter|toLowerCase|string|browser|object|indexOf|microdata|LatLng|maps|google|new|else|children|_trigger|map|setAttribute|version|createElement|getElementsByTagName|join|type|id|mozilla|inArray'.split('|'),0,{}))
|
|
@ -1,152 +0,0 @@
|
|||||||
/*!
|
|
||||||
* jQuery UI Google Maps 2.0
|
|
||||||
* http://code.google.com/p/jquery-ui-map/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010-2011 Johan Säll Larsson
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Depends:
|
|
||||||
* jquery.ui.core.js
|
|
||||||
* jquery.ui.widget.js
|
|
||||||
* jquery.ui.map.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
( function($) {
|
|
||||||
|
|
||||||
/* see http://en.wikipedia.org/wiki/XHTML_Friends_Network */
|
|
||||||
var XFN = [
|
|
||||||
'friend',
|
|
||||||
'contact',
|
|
||||||
'acquaintance'
|
|
||||||
];
|
|
||||||
|
|
||||||
/* Supported properties */
|
|
||||||
var properties = [
|
|
||||||
'summary',
|
|
||||||
'description',
|
|
||||||
'url',
|
|
||||||
'photo',
|
|
||||||
'street-address',
|
|
||||||
'postal-code',
|
|
||||||
'locality',
|
|
||||||
'region',
|
|
||||||
'latitude',
|
|
||||||
'longitude',
|
|
||||||
'startDate',
|
|
||||||
'dtstart',
|
|
||||||
'endDate',
|
|
||||||
'dtend',
|
|
||||||
'duration',
|
|
||||||
'eventType',
|
|
||||||
'category',
|
|
||||||
'fn',
|
|
||||||
'name',
|
|
||||||
'nickname',
|
|
||||||
'title',
|
|
||||||
'role',
|
|
||||||
'org',
|
|
||||||
'tel',
|
|
||||||
'reviewer',
|
|
||||||
'dtreviewed',
|
|
||||||
'rating'
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
$.extend($.ui.gmap, {
|
|
||||||
|
|
||||||
version: '1.0',
|
|
||||||
|
|
||||||
microformat: function(ns, callback) {
|
|
||||||
$('.'+ns).each(function(i, node) {
|
|
||||||
$.ui.gmap._trigger(callback, i, $(node), getItem($(node), []));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function hasProperty(property) {
|
|
||||||
for( var i = 0; i < properties.length; i++) {
|
|
||||||
if ( properties[i] === property ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasXFN(xfn) {
|
|
||||||
for( var i = 0; i < XFN.length; i++) {
|
|
||||||
if ( XFN[i] === xfn ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItem(node, list) {
|
|
||||||
|
|
||||||
node.children().each(function() {
|
|
||||||
|
|
||||||
var childNode = $(this);
|
|
||||||
|
|
||||||
if ( childNode.attr('class') != undefined ) {
|
|
||||||
$.each(childNode.attr('class').split(' '), function(i, c) {
|
|
||||||
if ( c.length > 0 && hasProperty(c) ) {
|
|
||||||
if ( !list[c] ) {
|
|
||||||
list[c] = {};
|
|
||||||
}
|
|
||||||
if ( childNode.attr('id') != '' ) {
|
|
||||||
list[c].id = childNode.attr('id');
|
|
||||||
}
|
|
||||||
if ( childNode.attr('title') != '' ) {
|
|
||||||
list[c].title = childNode.attr('title');
|
|
||||||
}
|
|
||||||
if ( childNode.attr('href') != undefined ) {
|
|
||||||
list[c].href = childNode.attr('href');
|
|
||||||
}
|
|
||||||
if ( childNode.attr('src') != undefined ) {
|
|
||||||
list[c].src = childNode.attr('src');
|
|
||||||
}
|
|
||||||
if ( childNode.text() != '' ) {
|
|
||||||
list[c].text = childNode.text();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( childNode.attr('rel') != undefined ) {
|
|
||||||
$.each(childNode.attr('rel').split(' '), function(i, c) {
|
|
||||||
if ( c.length > 0 && hasXFN(c) ) {
|
|
||||||
if (!list[c]) {
|
|
||||||
list[c] = [];
|
|
||||||
}
|
|
||||||
list[c].push({ 'text': childNode.text(), 'href': childNode.attr('href') });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getItem(childNode, list);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return list;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} (jQuery) );
|
|
29
soundmap/js/jquery.ui.gmap.microformat.min.js
vendored
@ -1,29 +0,0 @@
|
|||||||
/*!
|
|
||||||
* jQuery UI Google Maps 1.0.0
|
|
||||||
* http://code.google.com/p/jquery-ui-map/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 Johan Säll Larsson
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Depends:
|
|
||||||
* jquery.ui.core.js
|
|
||||||
* jquery.ui.widget.js
|
|
||||||
*/
|
|
||||||
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(6($){9 m=[\'O\',\'L\',\'R\'];9 j=[\'M\',\'N\',\'U\',\'Q\',\'T-S\',\'V-I\',\'E\',\'D\',\'C\',\'F\',\'G\',\'J\',\'K\',\'H\',\'B\',\'P\',\'Z\',\'18\',\'17\',\'16\',\'g\',\'1a\',\'1b\',\'1c\',\'1d\',\'19\',\'14\'];$.15($.s.t,{Y:\'1.0\',X:6(r,u){$(\'.\'+r).d(6(i,8){$.s.t.W(u,i,$(8),k($(8),[]))})}});6 w(q){n(9 i=0;i<j.f;i++){5(j[i]===q){a v}};a o}6 y(p){n(9 i=0;i<m.f;i++){5(m[i]===p){a v}};a o}6 k(8,3){8.11().d(6(){9 2=$(13);5(2.4(\'z\')!=e){$.d(2.4(\'z\').A(\' \'),6(i,c){5(c.f>0&&w(c)){5(!3[c]){3[c]={}}5(2.4(\'l\')!=\'\'){3[c].l=2.4(\'l\')}5(2.4(\'g\')!=\'\'){3[c].g=2.4(\'g\')}5(2.4(\'b\')!=e){3[c].b=2.4(\'b\')}5(2.4(\'h\')!=e){3[c].h=2.4(\'h\')}5(2.7()!=\'\'){3[c].7=2.7()}}})}5(2.4(\'x\')!=e){$.d(2.4(\'x\').A(\' \'),6(i,c){5(c.f>0&&y(c)){5(!3[c]){3[c]=[]}3[c].12({\'7\':2.7(),\'b\':2.4(\'b\')})}})}k(2,3)});a 3}}(10));',62,76,'||childNode|list|attr|if|function|text|node|var|return|href||each|undefined|length|title|src||properties|getItem|id|XFN|for|false|xfn|property|ns|ui|gmap|callback|true|hasProperty|rel|hasXFN|class|split|duration|latitude|region|locality|longitude|startDate|dtend|code|dtstart|endDate|contact|summary|description|friend|eventType|photo|acquaintance|address|street|url|postal|_trigger|microformat|version|category|jQuery|children|push|this|rating|extend|nickname|name|fn|dtreviewed|role|org|tel|reviewer'.split('|'),0,{}))
|
|
@ -1,110 +0,0 @@
|
|||||||
/*!
|
|
||||||
* jQuery UI Google Maps 2.0
|
|
||||||
* http://code.google.com/p/jquery-ui-map/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 Johan Säll Larsson
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Depends:
|
|
||||||
* jquery.ui.core.js
|
|
||||||
* jquery.ui.widget.js
|
|
||||||
* jquery.ui.map.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
( function($) {
|
|
||||||
|
|
||||||
jQuery.fn.extend({
|
|
||||||
|
|
||||||
items: getItems
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function splitTokens(s) {
|
|
||||||
if (s && /\S/.test(s))
|
|
||||||
return s.replace(/^\s+|\s+$/g,'').split(/\s+/);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItems(types) {
|
|
||||||
var selector = jQuery.map(splitTokens(types), function(t) {
|
|
||||||
return '[typeof~="'+t.replace(/"/g, '\\"')+'"]';
|
|
||||||
}).join(',') || '*';
|
|
||||||
// filter results to only match top-level items
|
|
||||||
// because [attr] selector doesn't work in IE we have to
|
|
||||||
// filter the elements. http://dev.jquery.com/ticket/5637
|
|
||||||
return jQuery(selector, this).filter(function() {
|
|
||||||
return (this.getAttribute('typeof') != null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getItem(node, list) {
|
|
||||||
|
|
||||||
node.children().each(function() {
|
|
||||||
|
|
||||||
var childNode = $(this);
|
|
||||||
var property = childNode.attr('property');
|
|
||||||
|
|
||||||
if ( property != undefined && property != null && property != '' && typeof property == 'string' ) {
|
|
||||||
if ( !list[property] ) {
|
|
||||||
list[property] = {};
|
|
||||||
}
|
|
||||||
if ( childNode.attr('content') != undefined ) {
|
|
||||||
list[property].content = childNode.attr('content');
|
|
||||||
}
|
|
||||||
if ( childNode.attr('href') != '' ) {
|
|
||||||
list[property].href = childNode.attr('href');
|
|
||||||
}
|
|
||||||
if ( childNode.attr('rel') != undefined ) {
|
|
||||||
list[property].rel = childNode.attr('rel');
|
|
||||||
}
|
|
||||||
if ( childNode.attr('src') != undefined ) {
|
|
||||||
list[property].src = childNode.attr('src');
|
|
||||||
}
|
|
||||||
if ( childNode.text() != '' ) {
|
|
||||||
list[property].text = childNode.text();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getItem(childNode, list);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return list;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$.extend($.ui.gmap, {
|
|
||||||
|
|
||||||
rdfa: function(ns, callback) {
|
|
||||||
|
|
||||||
var items = jQuery(document).items(ns);
|
|
||||||
//console.log(items);
|
|
||||||
items.each(function(i, node) {
|
|
||||||
var item = getItem($(node), []);
|
|
||||||
$.ui.gmap._trigger(callback, i, $(node), item);
|
|
||||||
//console.log(item);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
} (jQuery) );
|
|
29
soundmap/js/jquery.ui.gmap.rdfa.min.js
vendored
@ -1,29 +0,0 @@
|
|||||||
/*!
|
|
||||||
* jQuery UI Google Maps 1.0.0
|
|
||||||
* http://code.google.com/p/jquery-ui-map/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 Johan Säll Larsson
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Depends:
|
|
||||||
* jquery.ui.core.js
|
|
||||||
* jquery.ui.widget.js
|
|
||||||
*/
|
|
||||||
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(3($){8.C.v({a:p});3 q(s){5(s&&/\\F/.B(s))6 s.w(/^\\s+|\\s+$/g,\'\').E(/\\s+/);6[]}3 p(r){7 u=8.D(q(r),3(t){6\'[e~="\'+t.w(/"/g,\'\\\\"\')+\'"]\'}).N(\',\')||\'*\';6 8(u,d).M(3(){6(d.G(\'e\')!=n)})}3 l(9,2){9.L().y(3(){7 0=$(d);7 1=0.4(\'1\');5(1!=b&&1!=n&&1!=\'\'&&e 1==\'K\'){5(!2[1]){2[1]={}}5(0.4(\'h\')!=b){2[1].h=0.4(\'h\')}5(0.4(\'k\')!=\'\'){2[1].k=0.4(\'k\')}5(0.4(\'j\')!=b){2[1].j=0.4(\'j\')}5(0.4(\'f\')!=b){2[1].f=0.4(\'f\')}5(0.c()!=\'\'){2[1].c=0.c()}}l(0,2)});6 2}$.v($.o.m,{J:3(z,A){7 a=8(I).a(z);a.y(3(i,9){7 x=l($(9),[]);$.o.m.H(A,i,$(9),x)})}})}(8));',50,50,'childNode|property|list|function|attr|if|return|var|jQuery|node|items|undefined|text|this|typeof|src||content||rel|href|getItem|gmap|null|ui|getItems|splitTokens|types|||selector|extend|replace|item|each|ns|callback|test|fn|map|split|S|getAttribute|_trigger|document|rdfa|string|children|filter|join'.split('|'),0,{}))
|
|
@ -17,7 +17,7 @@ header("Cache-Control: post-check=0, pre-check=0", false);
|
|||||||
header("Pragma: no-cache");
|
header("Pragma: no-cache");
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
$targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
|
$targetDir = ini_get("upload_tmp_dir");
|
||||||
//$targetDir = 'uploads/';
|
//$targetDir = 'uploads/';
|
||||||
|
|
||||||
//$cleanupTargetDir = false; // Remove old files
|
//$cleanupTargetDir = false; // Remove old files
|
||||||
|
@ -2,9 +2,16 @@
|
|||||||
jQuery(document).ready(function($) {
|
jQuery(document).ready(function($) {
|
||||||
// $() will work as an alias for jQuery() inside of this function
|
// $() will work as an alias for jQuery() inside of this function
|
||||||
var map_canvas = $('#map_canvas');
|
var map_canvas = $('#map_canvas');
|
||||||
|
|
||||||
var soundmark;
|
var soundmark;
|
||||||
if (map_canvas){
|
if (map_canvas){
|
||||||
$('#map_canvas').gmap({'callback': function(map){
|
$('#map_canvas').gmap({'callback': function(map){
|
||||||
|
if($('#soundmap-marker-lat').val()!=""){
|
||||||
|
var latlng = new google.maps.LatLng($('#soundmap-marker-lat').val(), $('#soundmap-marker-lng').val());
|
||||||
|
map.panTo(latlng);
|
||||||
|
soundmark = map_canvas.gmap('addMarker', {'position': latlng, 'title':'', 'draggable':true}, function(map, marker){
|
||||||
|
});
|
||||||
|
}
|
||||||
$(map).click( function (event){
|
$(map).click( function (event){
|
||||||
if (soundmark == undefined){
|
if (soundmark == undefined){
|
||||||
soundmark = map_canvas.gmap('addMarker', {'position': event.latLng, 'title':'', 'draggable':true}, function(map, marker){
|
soundmark = map_canvas.gmap('addMarker', {'position': event.latLng, 'title':'', 'draggable':true}, function(map, marker){
|
||||||
@ -26,6 +33,18 @@ jQuery(document).ready(function($) {
|
|||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('#soundmap-marker-lat, #soundmap-marker-lng').change(function(){
|
||||||
|
var latlng = new google.maps.LatLng($('#soundmap-marker-lat').val(), $('#soundmap-marker-lng').val());
|
||||||
|
map = map_canvas.gmap('getMap');
|
||||||
|
map.panTo(latlng);
|
||||||
|
if(soundmark == undefined){
|
||||||
|
soundmark = map_canvas.gmap('addMarker', {'position': latlng, 'title':'', 'draggable':true}, function(map, marker){});
|
||||||
|
}else{
|
||||||
|
var marker = soundmark.get(0);
|
||||||
|
marker.setPosition(latlng);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("#uploader").pluploadQueue({
|
$("#uploader").pluploadQueue({
|
||||||
// General settings
|
// General settings
|
||||||
runtimes : 'gears,flash,silverlight,browserplus,html5',
|
runtimes : 'gears,flash,silverlight,browserplus,html5',
|
||||||
@ -43,7 +62,30 @@ jQuery(document).ready(function($) {
|
|||||||
flash_swf_url : WP_Params.plugin_url + 'js/plupload/plupload.flash.swf',
|
flash_swf_url : WP_Params.plugin_url + 'js/plupload/plupload.flash.swf',
|
||||||
|
|
||||||
// Silverlight settings
|
// Silverlight settings
|
||||||
silverlight_xap_url : WP_Params.plugin_url + 'js/plupload/plupload.silverlight.xap'
|
silverlight_xap_url : WP_Params.plugin_url + 'js/plupload/plupload.silverlight.xap',
|
||||||
|
//Events
|
||||||
|
init : {
|
||||||
|
FileUploaded: function(up, file, info) {
|
||||||
|
// Called when a file has finished uploading
|
||||||
|
//log('[FileUploaded] File:', file, "Info:", info);
|
||||||
|
var data = {
|
||||||
|
action: 'soundmap_file_uploaded',
|
||||||
|
file_name: file,
|
||||||
|
file_info: info
|
||||||
|
};
|
||||||
|
$.post(ajaxurl, data, function(response) {
|
||||||
|
result = $.parseJSON(response);
|
||||||
|
if (result.error != ""){
|
||||||
|
alert (result.error);
|
||||||
|
}else{
|
||||||
|
table = $('#sound-att-table');
|
||||||
|
table.append ('<tr><td class="soundmap-att-left">' + result.fileName + '</td><td>' + result.length + '</td></tr>');
|
||||||
|
box = $('#soundmap-attachments');
|
||||||
|
box.append ('<input type="hidden" name="soundmap_attachments_id[]" value="' + result.attachment + '">');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#post').submit(function(e) {
|
$('#post').submit(function(e) {
|
||||||
@ -61,10 +103,21 @@ jQuery(document).ready(function($) {
|
|||||||
|
|
||||||
uploader.start();
|
uploader.start();
|
||||||
} else
|
} else
|
||||||
alert('You must at least upload one file.');
|
// alert('You must at least upload one file.');
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#soundmap-marker-datepicker').DatePicker({
|
||||||
|
format:'d/m/Y',
|
||||||
|
date: $('#soundmap-marker-date').val(),
|
||||||
|
current: $('#soundmap-marker-date').val(),
|
||||||
|
starts: 1,
|
||||||
|
flat: true,
|
||||||
|
onChange: function(formated, dates){
|
||||||
|
$('#soundmap-marker-date').val(formated);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
42
soundmap/js/soundmap-wp.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
jQuery(document).ready(function($) {
|
||||||
|
// $() will work as an alias for jQuery() inside of this function
|
||||||
|
var map_canvas = $('.map_canvas');
|
||||||
|
var g_map;
|
||||||
|
map_canvas.after('<div id="hidden-markers-content" style ="display:hidden;"></div>')
|
||||||
|
info_w = false;
|
||||||
|
if (map_canvas){
|
||||||
|
markers_map = $('.map_canvas').gmap({'callback': function(map){
|
||||||
|
g_map=map;
|
||||||
|
info_w = new google.maps.InfoWindow({content: ' '});
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
action: 'soundmap_JSON_load_markers'
|
||||||
|
};
|
||||||
|
$.post(WP_Params.ajaxurl, data, function(response) {
|
||||||
|
result = $.parseJSON(response);
|
||||||
|
$.each( result, function(i, m) {
|
||||||
|
$('.map_canvas').gmap('addMarker', { 'position': new google.maps.LatLng(m.lat, m.lng) }).data('postid', m.id).click(function(){
|
||||||
|
id=$(this).data('postid');
|
||||||
|
marker = $(this).get(0);
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
action: 'soundmap_load_infowindow',
|
||||||
|
marker: id
|
||||||
|
};
|
||||||
|
|
||||||
|
$.post(WP_Params.ajaxurl, data, function(response){
|
||||||
|
info_w.close();
|
||||||
|
$("#hidden-markers-content").append(response);
|
||||||
|
info_w.setContent($("#hidden-markers-content").children().get(0));
|
||||||
|
info_w.open(g_map, marker);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
48
soundmap/modules/module.audioplayer.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class sm_AudioPlayer extends SoundMap_Player{
|
||||||
|
|
||||||
|
var $capabilities;
|
||||||
|
var $options;
|
||||||
|
|
||||||
|
function sm_AudioPlayer(){
|
||||||
|
$this->_load_capabilites();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _load_capabilites(){
|
||||||
|
$capabilities = array();
|
||||||
|
$capabilities['playLists'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_audio_content($files, $id){
|
||||||
|
|
||||||
|
global $AudioPlayer;
|
||||||
|
|
||||||
|
$playlist = FALSE;
|
||||||
|
$total_files = count($files);
|
||||||
|
|
||||||
|
if (!$total_files)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($total_files>1)
|
||||||
|
$playlist = TRUE;
|
||||||
|
|
||||||
|
$file_links = array();
|
||||||
|
foreach($files as $file){
|
||||||
|
$file_links[] = $file['fileURI'];
|
||||||
|
}
|
||||||
|
$param = "";
|
||||||
|
if ($playlist){
|
||||||
|
$param_files = implode(',', $file_links);
|
||||||
|
}else{
|
||||||
|
$param_files = $file_links[0];
|
||||||
|
}
|
||||||
|
$param = '[audio:' . $param_files . '|autostart=yes]';
|
||||||
|
$out = "";
|
||||||
|
$out = $AudioPlayer->processContent($param);
|
||||||
|
$out_script = '<script type="text/javascript">'. $AudioPlayer->footerCode . '</script>';
|
||||||
|
return $out . $out_script;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
soundmap/modules/module.base.player.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class Soundmap_Player {
|
||||||
|
|
||||||
|
function Soundmap_Player (){
|
||||||
|
$da = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
39
soundmap/modules/module.haikuplayer.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class sm_HaikuPlayer extends SoundMap_Player{
|
||||||
|
|
||||||
|
var $capabilities;
|
||||||
|
var $options;
|
||||||
|
|
||||||
|
function sm_HaikuPlayer(){
|
||||||
|
$this->_load_capabilites();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _load_capabilites(){
|
||||||
|
$capabilities = array();
|
||||||
|
$capabilities['playLists'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_audio_content($files, $id){
|
||||||
|
|
||||||
|
$total_files = count($files);
|
||||||
|
|
||||||
|
if (!$total_files)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($total_files>1)
|
||||||
|
|
||||||
|
|
||||||
|
$file_links = array();
|
||||||
|
$out = '';
|
||||||
|
foreach($files as $file){
|
||||||
|
$atts['url'] = $file['fileURI'];
|
||||||
|
$out .= haiku_player_shortcode($atts);
|
||||||
|
}
|
||||||
|
$out_script = '<script type="text/javascript"> load_haiku_players(); </script>';
|
||||||
|
|
||||||
|
return $out . $out_script;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
soundmap/modules/module.jplayer.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class sm_jPlayer extends SoundMap_Player{
|
||||||
|
|
||||||
|
var $capabilities;
|
||||||
|
var $options;
|
||||||
|
|
||||||
|
function sm_jPlayer(){
|
||||||
|
$this->_load_capabilites();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _load_capabilites(){
|
||||||
|
$capabilities = array();
|
||||||
|
$capabilities['playLists'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_audio_content($files, $id){
|
||||||
|
|
||||||
|
|
||||||
|
$playlist = FALSE;
|
||||||
|
$total_files = count($files);
|
||||||
|
|
||||||
|
if (!$total_files)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($total_files>1)
|
||||||
|
$playlist = TRUE;
|
||||||
|
|
||||||
|
$out = "";
|
||||||
|
$out = jplayer_insert($files, $id, TRUE);
|
||||||
|
//$out_script = '<script type="text/javascript">'. $AudioPlayer->footerCode . '</script>';
|
||||||
|
return $out; // . $out_script;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
soundmap/modules/module.wp-audio-gallery-player.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class sm_AudioGallery_Player extends SoundMap_Player{
|
||||||
|
|
||||||
|
var $capabilities;
|
||||||
|
var $options;
|
||||||
|
|
||||||
|
function sm_AudioGallery_Player(){
|
||||||
|
$this->_load_capabilites();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _load_capabilites(){
|
||||||
|
$capabilities = array();
|
||||||
|
$capabilities['playLists'] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_audio_content($files, $id){
|
||||||
|
|
||||||
|
$total_files = count($files);
|
||||||
|
|
||||||
|
if (!$total_files)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($total_files>1)
|
||||||
|
|
||||||
|
|
||||||
|
$file_links = array();
|
||||||
|
$out = '';
|
||||||
|
$out = wp_audio_gallery_playlist('[WP AUDIO PLAYLIST]');
|
||||||
|
// $out_script = '<script type="text/javascript"> load_haiku_players(); </script>';
|
||||||
|
|
||||||
|
return $out;// . $out_script;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,15 +8,27 @@
|
|||||||
Plugin Name: Soundmap
|
Plugin Name: Soundmap
|
||||||
Plugin URI: http://www.soinumapa.net
|
Plugin URI: http://www.soinumapa.net
|
||||||
Description: New version of the Soinumapa Plugin for creating sound maps
|
Description: New version of the Soinumapa Plugin for creating sound maps
|
||||||
Version: 2.5.3
|
Version: 0.4
|
||||||
Author: Xavier Balderas
|
Author: Xavier Balderas
|
||||||
Author URI: http://www.xavierbalderas.com
|
Author URI: http://www.xavierbalderas.com
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
require_once (WP_PLUGIN_DIR . "/soundmap/api/getid3.php");
|
||||||
|
require_once (WP_PLUGIN_DIR . "/soundmap/modules/module.base.player.php");
|
||||||
|
require_once (WP_PLUGIN_DIR . "/soundmap/modules/module.audioplayer.php");
|
||||||
|
require_once (WP_PLUGIN_DIR . "/soundmap/modules/module.haikuplayer.php");
|
||||||
|
require_once (WP_PLUGIN_DIR . "/soundmap/modules/module.wp-audio-gallery-player.php");
|
||||||
|
require_once (WP_PLUGIN_DIR . "/soundmap/modules/module.jplayer.php");
|
||||||
|
|
||||||
|
|
||||||
function soundmap_init() {
|
function soundmap_init() {
|
||||||
|
|
||||||
|
global $soundmap;
|
||||||
|
|
||||||
|
$soundmap = array();
|
||||||
|
$soundmap['on_page'] = FALSE;
|
||||||
|
|
||||||
soundmap_register_scripts();
|
soundmap_register_scripts();
|
||||||
|
|
||||||
$labels = array(
|
$labels = array(
|
||||||
@ -34,7 +46,6 @@ function soundmap_init() {
|
|||||||
'parent_item_colon' => '',
|
'parent_item_colon' => '',
|
||||||
'menu_name' => 'Markers'
|
'menu_name' => 'Markers'
|
||||||
);
|
);
|
||||||
|
|
||||||
$args = array(
|
$args = array(
|
||||||
'labels' => $labels,
|
'labels' => $labels,
|
||||||
'public' => true,
|
'public' => true,
|
||||||
@ -51,6 +62,60 @@ function soundmap_init() {
|
|||||||
'supports' => array('title','editor','thumbnail')
|
'supports' => array('title','editor','thumbnail')
|
||||||
);
|
);
|
||||||
register_post_type('marker',$args);
|
register_post_type('marker',$args);
|
||||||
|
register_taxonomy_for_object_type('category', 'marker');
|
||||||
|
register_taxonomy_for_object_type('post_tag', 'marker');
|
||||||
|
|
||||||
|
soundmap_check_map_page();
|
||||||
|
|
||||||
|
soundmap_create_player_instance();
|
||||||
|
|
||||||
|
if(!is_admin()){
|
||||||
|
soundmap_register_wp_scripts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function soundmap_create_player_instance(){
|
||||||
|
|
||||||
|
global $soundmap_Player;
|
||||||
|
|
||||||
|
$plugins = get_option( 'active_plugins', array() );
|
||||||
|
|
||||||
|
if (!is_array($plugins))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(in_array('audio-player/audio-player.php', $plugins) && class_exists('sm_AudioPlayer')){
|
||||||
|
//Audio player active
|
||||||
|
$soundmap_Player = new sm_AudioPlayer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_array('haiku-minimalist-audio-player/haiku-player.php', $plugins) && class_exists('sm_HaikuPlayer')){
|
||||||
|
//Audio player active
|
||||||
|
$soundmap_Player = new sm_HaikuPlayer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_array('wp-audio-gallery-playlist/wp-audio-gallery-playlist.php', $plugins) && class_exists('sm_AudioGallery_Player')){
|
||||||
|
//Audio player active
|
||||||
|
$soundmap_Player = new sm_AudioGallery_Player();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_array('jplayer/jplayer.php', $plugins) && class_exists('sm_jPlayer')){
|
||||||
|
//Audio player active
|
||||||
|
$soundmap_Player = new sm_jPlayer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_check_map_page(){
|
||||||
|
global $soundmap;
|
||||||
|
$uri = get_uri();
|
||||||
|
if (end($uri) == 'map/'){
|
||||||
|
$soundmap['on_page'] = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function soundmap_register_scripts(){
|
function soundmap_register_scripts(){
|
||||||
@ -63,17 +128,67 @@ function soundmap_register_scripts(){
|
|||||||
|
|
||||||
|
|
||||||
function soundmap_metaboxes_register_callback(){
|
function soundmap_metaboxes_register_callback(){
|
||||||
add_meta_box('sounmap-map', __("Place the Marker", 'soundmap'), 'soundmap_map_meta_box', 'marker', 'normal', 'high');
|
add_meta_box('soundmap-map', __("Place the Marker", 'soundmap'), 'soundmap_map_meta_box', 'marker', 'normal', 'high');
|
||||||
add_meta_box('sounmap-sound-file', __("Add a sound file", 'soundmap'), 'soundmap_upload_file_meta_box', 'marker', 'side', 'high');
|
add_meta_box('soundmap-sound-file', __("Add a sound file", 'soundmap'), 'soundmap_upload_file_meta_box', 'marker', 'normal', 'high');
|
||||||
|
add_meta_box('soundmap-sound-info', __("Add info for the marker", 'soundmap'), 'soundmap_info_meta_box', 'marker', 'side', 'high');
|
||||||
|
add_meta_box('soundmap-sound-attachments', __("Sound files attached.", 'soundmap'), 'soundmap_attachments_meta_box', 'marker', 'side', 'high');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function soundmap_info_meta_box(){
|
||||||
|
|
||||||
|
global $post;
|
||||||
|
|
||||||
|
$soundmap_author = get_post_meta($post->ID, 'soundmap_marker_author', TRUE);
|
||||||
|
$soundmap_date = get_post_meta($post->ID, 'soundmap_marker_date', TRUE);
|
||||||
|
|
||||||
|
echo '<label for="soundmap-marker-author">' . __('Author', 'soundmap') . ': </label>';
|
||||||
|
echo '<input type="text" name="soundmap_marker_author" id="soundmap-marker-author" value="' . $soundmap_author . '">';
|
||||||
|
echo '<input type="hidden" name="soundmap_marker_date" id="soundmap-marker-date" value="'. $soundmap_date.'">';
|
||||||
|
echo '<p id="soundmap-marker-datepicker"></p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_attachments_meta_box(){
|
||||||
|
global $post;
|
||||||
|
|
||||||
|
$files = get_post_meta($post->ID, 'soundmap_attachments_id', FALSE);
|
||||||
|
|
||||||
|
|
||||||
|
echo '<div id="soundmap-attachments">';
|
||||||
|
echo '<table cellspacing="0" cellpadding="0" id="sound-att-table">';
|
||||||
|
echo '<tr><th class="soundmap-att-left">' . __('Filename', 'soundmap') . '</th><th>' . __('Length', 'soundmap') .'</th></tr>';
|
||||||
|
$rows = '';
|
||||||
|
$fields = '';
|
||||||
|
|
||||||
|
foreach ($files as $key => $value){
|
||||||
|
|
||||||
|
$att = get_post($value);
|
||||||
|
$f_name = $att->post_name;
|
||||||
|
$f_info = soundmap_get_id3info(get_attached_file($value));
|
||||||
|
$rows .= '<tr><td class="soundmap-att-left">' . $f_name . '</td><td>' . $f_info['play_time'] . '</td></tr>';
|
||||||
|
$fields .='<input type="hidden" name="soundmap_attachments_id[]" value="' . $value . '">';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $rows;
|
||||||
|
echo '</table>';
|
||||||
|
echo $fields;
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
function soundmap_map_meta_box(){
|
function soundmap_map_meta_box(){
|
||||||
|
|
||||||
|
global $post;
|
||||||
|
|
||||||
|
$soundmap_lat = get_post_meta($post->ID, 'soundmap_marker_lat', TRUE);
|
||||||
|
$soundmap_lng = get_post_meta($post->ID, 'soundmap_marker_lng', TRUE);
|
||||||
|
|
||||||
echo '<input type="hidden" name="soundmap_map_noncename" id="soundmap_map_noncename" value="' .
|
echo '<input type="hidden" name="soundmap_map_noncename" id="soundmap_map_noncename" value="' .
|
||||||
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
|
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
|
||||||
echo '<div id="map_canvas"></div>';
|
echo '<div id="map_canvas"></div>';
|
||||||
echo '<label for="soundmap-marker-lat">' . __('Latitud', 'soundmap') . '</label>';
|
echo '<label for="soundmap-marker-lat">' . __('Latitud', 'soundmap') . '</label>';
|
||||||
echo '<input type="text" name="soundmap_marker_lat" id="soundmap-marker-lat" value="0">';
|
echo '<input type="text" name="soundmap_marker_lat" id="soundmap-marker-lat" value = "' . $soundmap_lat . '">';
|
||||||
echo '<label for="soundmap-marker-lng">' . __('Longitud', 'soundmap') . '</label>';
|
echo '<label for="soundmap-marker-lng">' . __('Longitud', 'soundmap') . '</label>';
|
||||||
echo '<input type="text" name="soundmap_marker_lng" id="soundmap-marker-lng" value="0">';
|
echo '<input type="text" name="soundmap_marker_lng" id="soundmap-marker-lng" value = "'. $soundmap_lng . '">';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,14 +203,20 @@ function soundmap_rewrite_flush() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function soundmap_register_admin_scripts() {
|
function soundmap_register_admin_scripts() {
|
||||||
wp_register_script('soundmap-admin', WP_PLUGIN_URL . '/soundmap/js/soundmap-admin.js', array('jquery-google-maps', 'jquery-plupload'));
|
wp_register_script('soundmap-admin', WP_PLUGIN_URL . '/soundmap/js/soundmap-admin.js', array('jquery-google-maps', 'jquery-plupload', 'jquery-datepicker'));
|
||||||
wp_register_style("soundmap-admin", WP_PLUGIN_URL . '/soundmap/css/soundmap-admin.css', array('plupload-style'));
|
wp_register_style("soundmap-admin", WP_PLUGIN_URL . '/soundmap/css/soundmap-admin.css', array('plupload-style', 'jquery-datepicker'));
|
||||||
|
|
||||||
//Register PLUPLOAD
|
//Register PLUPLOAD
|
||||||
wp_register_style('plupload-style',WP_PLUGIN_URL . '/soundmap/css/jquery.plupload.queue.css');
|
wp_register_style('plupload-style',WP_PLUGIN_URL . '/soundmap/css/jquery.plupload.queue.css');
|
||||||
wp_register_script('plupload', WP_PLUGIN_URL . '/soundmap/js/plupload/plupload.full.js');
|
wp_register_script('plupload', WP_PLUGIN_URL . '/soundmap/js/plupload/plupload.full.js');
|
||||||
wp_register_script('jquery-plupload', WP_PLUGIN_URL . '/soundmap/js/plupload/jquery.plupload.queue.js', array('plupload'));
|
wp_register_script('jquery-plupload', WP_PLUGIN_URL . '/soundmap/js/plupload/jquery.plupload.queue.js', array('plupload'));
|
||||||
|
//Register DATEPICKER
|
||||||
|
wp_register_script('jquery-datepicker', WP_PLUGIN_URL . '/soundmap/js/jquery.datepicker.js', array('jquery'));
|
||||||
|
wp_register_style('jquery-datepicker', WP_PLUGIN_URL . '/soundmap/css/jquery.datepicker.css');
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_register_wp_scripts() {
|
||||||
|
wp_register_script('soundmap', WP_PLUGIN_URL . '/soundmap/js/soundmap-wp.js', array('jquery-google-maps'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function soundmap_admin_enqueue_scripts() {
|
function soundmap_admin_enqueue_scripts() {
|
||||||
@ -108,6 +229,12 @@ function soundmap_admin_enqueue_scripts() {
|
|||||||
wp_localize_script('soundmap-admin','WP_Params',$params);
|
wp_localize_script('soundmap-admin','WP_Params',$params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function soundmap_wp_enqueue_scripts() {
|
||||||
|
wp_enqueue_script('soundmap');
|
||||||
|
|
||||||
|
wp_localize_script( 'soundmap', 'WP_Params', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
function soundmap_save_options(){
|
function soundmap_save_options(){
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -140,37 +267,240 @@ function soundmap_save_post($post_id) {
|
|||||||
|
|
||||||
$soundmark_lat = $_POST['soundmap_marker_lat'];
|
$soundmark_lat = $_POST['soundmap_marker_lat'];
|
||||||
$soundmark_lng = $_POST['soundmap_marker_lng'];
|
$soundmark_lng = $_POST['soundmap_marker_lng'];
|
||||||
|
$soundmark_author = $_POST['soundmap_marker_author'];
|
||||||
|
$soundmark_date = $_POST['soundmap_marker_date'];
|
||||||
|
|
||||||
add_post_meta($post_id, 'soundmap_marker_lat', $soundmark_lat, TRUE);
|
add_post_meta($post_id, 'soundmap_marker_lat', $soundmark_lat, TRUE);
|
||||||
add_post_meta($post_id, 'soundmap_marker_lng', $soundmark_lng, TRUE);
|
add_post_meta($post_id, 'soundmap_marker_lng', $soundmark_lng, TRUE);
|
||||||
|
add_post_meta($post_id, 'soundmap_marker_author', $soundmark_author, TRUE);
|
||||||
|
add_post_meta($post_id, 'soundmap_marker_date', $soundmark_date, TRUE);
|
||||||
|
|
||||||
|
|
||||||
//before searching on all the $_POST array, let's take a look if there is any upload first!
|
//before searching on all the $_POST array, let's take a look if there is any upload first!
|
||||||
if(!array_key_exists("uploader_0_name",$_POST))
|
if(isset($_POST['soundmap_attachments_id'])){
|
||||||
return;
|
$files = $_POST['soundmap_attachments_id'];
|
||||||
|
delete_post_meta($post_id, 'soundmap_attachments_id');
|
||||||
$files = preg_grep('/mp3$/', $_POST);
|
|
||||||
|
|
||||||
foreach ($files as $key => $value){
|
foreach ($files as $key => $value){
|
||||||
if(preg_match('/^uploader_[0-9]*_name$/',$key)){
|
add_post_meta($post_id, 'soundmap_attachments_id', $value);
|
||||||
$exp = explode('_', $key);
|
soundmap_attach_file($value, $post_id);
|
||||||
$number = $exp[1];
|
};
|
||||||
$name = $value;
|
};
|
||||||
$tmpname = $_POST['uploader_' . $number . '_tmpname'];
|
|
||||||
soundmap_add_sound_file($name, $tmpname, $post_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function soundmap_JSON_load_markers () {
|
||||||
|
$query = new WP_Query(array('post_type' => 'marker'));
|
||||||
|
$markers = array();
|
||||||
|
|
||||||
|
if ( !$query->have_posts() )
|
||||||
|
die();
|
||||||
|
$posts = $query->posts;
|
||||||
|
foreach($posts as $post){
|
||||||
|
$post_id = $post->ID;
|
||||||
|
$m_lat = get_post_meta($post_id,'soundmap_marker_lat', TRUE);
|
||||||
|
$m_lng = get_post_meta($post_id,'soundmap_marker_lng', TRUE);
|
||||||
|
$title = get_the_title ($post_id);
|
||||||
|
$mark = array(
|
||||||
|
'lat' => $m_lat,
|
||||||
|
'lng' => $m_lng,
|
||||||
|
'id' => $post_id,
|
||||||
|
'title' => $title
|
||||||
|
);
|
||||||
|
$markers[] = $mark;
|
||||||
|
}
|
||||||
|
echo json_encode($markers);
|
||||||
|
die();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_ajax_file_uploaded_callback() {
|
||||||
|
|
||||||
|
if (!isset($_REQUEST['file_name']))
|
||||||
|
die();
|
||||||
|
|
||||||
|
$rtn = array();
|
||||||
|
$rtn['error'] = "";
|
||||||
|
|
||||||
|
$file_data = $_REQUEST['file_name'];
|
||||||
|
|
||||||
|
if ($file_data['status'] != 5)
|
||||||
|
die();
|
||||||
|
|
||||||
|
$fileName = sanitize_file_name($file_data['name']);
|
||||||
|
|
||||||
|
//Check the directory.
|
||||||
|
$months_folders=get_option( 'uploads_use_yearmonth_folders' );
|
||||||
|
$wud = wp_upload_dir();
|
||||||
|
if ($wud['error']){
|
||||||
|
$rtn['error'] = $wud['error'];
|
||||||
|
echo json_encode ($rtn);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
$targetDir = $wud['path'];
|
||||||
|
$targetURL = $wud['url'];
|
||||||
|
//check if the file exists.
|
||||||
|
if (file_exists($targetDir . DIRECTORY_SEPARATOR . $fileName)) {
|
||||||
|
$ext = strrpos($fileName, '.');
|
||||||
|
$fileName_a = substr($fileName, 0, $ext);
|
||||||
|
$fileName_b = substr($fileName, $ext);
|
||||||
|
|
||||||
|
$count = 1;
|
||||||
|
while (file_exists($targetDir . DIRECTORY_SEPARATOR . $fileName_a . '_' . $count . $fileName_b))
|
||||||
|
$count++;
|
||||||
|
|
||||||
|
$fileName = $fileName_a . '_' . $count . $fileName_b;
|
||||||
|
}
|
||||||
|
$tempDir = ini_get("upload_tmp_dir");
|
||||||
|
//move it.
|
||||||
|
$fileDir = $targetDir . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
$fileURL = $targetURL . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
if(!rename($tempDir . DIRECTORY_SEPARATOR . $file_data['target_name'], $fileDir)){
|
||||||
|
$rtn['error'] = __('Error moving the file.','soundmap');
|
||||||
|
echo json_encode($rtn);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileInfo = soundmap_get_id3info($fileDir);
|
||||||
|
if(!$sound_attach_id = soundmap_add_media_attachment($fileDir, $fileURL))
|
||||||
|
die();
|
||||||
|
|
||||||
|
|
||||||
|
$rtn['attachment'] = $sound_attach_id;
|
||||||
|
$rtn['length'] = $fileInfo['play_time'];
|
||||||
|
$rtn['fileName'] = $fileName;
|
||||||
|
|
||||||
|
echo json_encode($rtn);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_add_media_attachment($file, $fileURL){
|
||||||
|
|
||||||
|
$wp_filetype = wp_check_filetype(basename($file), null );
|
||||||
|
$attachment = array(
|
||||||
|
'post_mime_type' => $wp_filetype['type'],
|
||||||
|
'post_title' => preg_replace('/\.[^.]+$/', '', basename($file)),
|
||||||
|
'post_content' => '',
|
||||||
|
'post_status' => 'inherit',
|
||||||
|
'guid' => $fileURL
|
||||||
|
);
|
||||||
|
$attach_id = wp_insert_attachment( $attachment, $file);
|
||||||
|
// you must first include the image.php file
|
||||||
|
// for the function wp_generate_attachment_metadata() to work
|
||||||
|
require_once(ABSPATH . 'wp-admin/includes/image.php');
|
||||||
|
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
|
||||||
|
wp_update_attachment_metadata( $attach_id, $attach_data );
|
||||||
|
return $attach_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_get_id3info($file){
|
||||||
|
$getID3 = new getID3;
|
||||||
|
$fileInfo = $getID3->analyze($file);
|
||||||
|
$result = array();
|
||||||
|
$result['play_time'] = $fileInfo['playtime_string'];
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_attach_file($att, $post_id){
|
||||||
|
global $wpdb;
|
||||||
|
return $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %d WHERE post_type = 'attachment' AND ID IN ( $att )", $post_id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_template_redirect(){
|
||||||
|
global $soundmap;
|
||||||
|
|
||||||
|
if ($soundmap['on_page']){
|
||||||
|
if ($theme=soundmap_get_template_include('map'))
|
||||||
|
include ($theme);
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function soundmap_add_sound_file ($name, $tmpname, $post_id){
|
function soundmap_get_template_include($templ){
|
||||||
// var_dump($name);
|
if (!$templ)
|
||||||
|
return FALSE;
|
||||||
|
$theme_file = TEMPLATEPATH . DIRECTORY_SEPARATOR . $templ . '.php';
|
||||||
|
$plugin_file = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'soundmap' . DIRECTORY_SEPARATOR . 'theme' . DIRECTORY_SEPARATOR . 'theme_' . $templ . '.php';
|
||||||
|
|
||||||
|
if (file_exists($theme_file))
|
||||||
|
return $theme_file;
|
||||||
|
|
||||||
|
if(file_exists($plugin_file))
|
||||||
|
return $plugin_file;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function soundmap_pre_get_posts( $query ) {
|
||||||
|
global $soundmap;
|
||||||
|
if ($soundmap['on_page'])
|
||||||
|
$query->parse_query( array('post_type'=>'marker') );
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
function soundmap_load_infowindow(){
|
||||||
|
$marker_id = $_REQUEST['marker'];
|
||||||
|
$marker = get_post( $marker_id);
|
||||||
|
global $post;
|
||||||
|
$post = $marker;
|
||||||
|
setup_postdata($marker);
|
||||||
|
if(!$marker)
|
||||||
|
die();
|
||||||
|
|
||||||
|
|
||||||
|
$info['m_author'] = get_post_meta($marker_id, 'soundmap_marker_author', TRUE);
|
||||||
|
$info['m_date'] = get_post_meta($marker_id, 'soundmap_marker_date', TRUE);
|
||||||
|
$files = get_post_meta($marker_id, 'soundmap_attachments_id', FALSE);
|
||||||
|
foreach ($files as $key => $value){
|
||||||
|
$file = array();
|
||||||
|
$file['id'] = $value;
|
||||||
|
$file['fileURI'] = wp_get_attachment_url($value);
|
||||||
|
$file['filePath'] = get_attached_file($value);
|
||||||
|
$file['info'] = soundmap_get_id3info($file['filePath']);
|
||||||
|
$info['m_files'][] = $file;
|
||||||
|
}
|
||||||
|
if ($theme=soundmap_get_template_include('window'))
|
||||||
|
include ($theme);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action('template_redirect', 'soundmap_template_redirect');
|
||||||
add_action('init', 'soundmap_init');
|
add_action('init', 'soundmap_init');
|
||||||
add_action('admin_enqueue_scripts', 'soundmap_admin_enqueue_scripts');
|
add_action('admin_enqueue_scripts', 'soundmap_admin_enqueue_scripts');
|
||||||
|
add_action('wp_enqueue_scripts', 'soundmap_wp_enqueue_scripts');
|
||||||
add_action('admin_init', 'soundmap_register_admin_scripts');
|
add_action('admin_init', 'soundmap_register_admin_scripts');
|
||||||
add_action('save_post', 'soundmap_save_post');
|
add_action('save_post', 'soundmap_save_post');
|
||||||
|
|
||||||
|
add_action('wp_ajax_soundmap_file_uploaded', 'soundmap_ajax_file_uploaded_callback');
|
||||||
|
add_action('wp_ajax_nopriv_soundmap_JSON_load_markers','soundmap_JSON_load_markers');
|
||||||
|
add_action('wp_ajax_nopriv_soundmap_load_infowindow','soundmap_load_infowindow');
|
||||||
|
|
||||||
|
add_filter( 'pre_get_posts', 'soundmap_pre_get_posts' );
|
||||||
|
|
||||||
register_activation_hook(__FILE__, 'soundmap_rewrite_flush');
|
register_activation_hook(__FILE__, 'soundmap_rewrite_flush');
|
||||||
|
|
||||||
|
|
||||||
|
function get_uri() {
|
||||||
|
$request_uri = $_SERVER['REQUEST_URI'];
|
||||||
|
// for consistency, check to see if trailing slash exists in URI request
|
||||||
|
if (substr($request_uri, -1)!="/") {
|
||||||
|
$request_uri = $request_uri."/";
|
||||||
|
}
|
||||||
|
preg_match_all('#[^/]+/#', $request_uri, $matches);
|
||||||
|
// could've used explode() above, but this is more consistent across varied WP installs
|
||||||
|
$uri = $matches[0];
|
||||||
|
return $uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_player_interface($files, $id){
|
||||||
|
|
||||||
|
if(!is_array($files))
|
||||||
|
return;
|
||||||
|
|
||||||
|
global $soundmap_Player;
|
||||||
|
|
||||||
|
$insert_content = $soundmap_Player->print_audio_content($files, $id);
|
||||||
|
echo $insert_content;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
3
soundmap/theme/theme_map.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#map-page{width:100%; height:100%; position:absolute; top:0; left:0;}
|
||||||
|
#map{width:100%; height:100%;}
|
||||||
|
.map_canvas{width:100%; height:100%;}
|
60
soundmap/theme/theme_map.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Header for the MAP default themplate
|
||||||
|
*
|
||||||
|
* Displays all of the <head> section and everything up till <div id="main">
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<!--[if IE 6]>
|
||||||
|
<html id="ie6" <?php language_attributes(); ?>>
|
||||||
|
<![endif]-->
|
||||||
|
<!--[if IE 7]>
|
||||||
|
<html id="ie7" <?php language_attributes(); ?>>
|
||||||
|
<![endif]-->
|
||||||
|
<!--[if IE 8]>
|
||||||
|
<html id="ie8" <?php language_attributes(); ?>>
|
||||||
|
<![endif]-->
|
||||||
|
<!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!-->
|
||||||
|
<html <?php language_attributes(); ?>>
|
||||||
|
<!--<![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="<?php bloginfo( 'charset' ); ?>" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<title><?php
|
||||||
|
$title = __('SoundMap', 'soundmap') . ' | ';
|
||||||
|
$title = apply_filters('wp_title', $title, "|", 'right');
|
||||||
|
|
||||||
|
echo $title;
|
||||||
|
|
||||||
|
bloginfo( 'name' );
|
||||||
|
|
||||||
|
?></title>
|
||||||
|
|
||||||
|
<link rel="profile" href="http://gmpg.org/xfn/11" />
|
||||||
|
<link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
|
||||||
|
<link rel="stylesheet" type="text/css" media="all" href="<?php echo WP_PLUGIN_URL ?>/soundmap/theme/theme_map.css" />
|
||||||
|
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<?php
|
||||||
|
/* Always have wp_head() just before the closing </head>
|
||||||
|
* tag of your theme, or you will break many plugins, which
|
||||||
|
* generally use this hook to add elements to <head> such
|
||||||
|
* as styles, scripts, and meta tags.
|
||||||
|
*/
|
||||||
|
wp_head();
|
||||||
|
?>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body <?php body_class(); ?>>
|
||||||
|
<div id="map-page" class="hfeed">
|
||||||
|
<div id="map">
|
||||||
|
<div class="map_canvas">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php wp_footer(); ?>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
soundmap/theme/theme_window.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="<?php post_class('', $marker_id) ?>">
|
||||||
|
<div class="post-title">
|
||||||
|
<?php echo get_the_title($marker_id); ?>
|
||||||
|
</div>
|
||||||
|
<div class="post-content">
|
||||||
|
<?php echo apply_filters('the_content',get_the_content()) ?>
|
||||||
|
<hr>
|
||||||
|
<p><?php echo __('Author', 'soundmap') . ': ' . $info['m_author']; ?></p>
|
||||||
|
<p><?php echo __('Date', 'soundmap') . ': ' . $info['m_date']; ?></p>
|
||||||
|
<hr>
|
||||||
|
<?php
|
||||||
|
add_player_interface($info['m_files'], $marker_id);
|
||||||
|
?>
|
||||||
|
<hr class="clear">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|