QuickTip: ExtJS 4 panel gombok

{lang: 'hu'}

Ma a következő dolog fordult velem elő: létrehoztam egy sima panelt, amelyre definiáltam 3 gombot is. A gombokhoz viszont renderelés után hozzá kellett férnem abból a célból, hogy ha a felhasználónak nincs megfelelő jogosultsága, ne tudja nyomkodni ezeket. Meglepődve tapasztaltam, hogy a panel.buttons property null értékkel rendelkezik, pedig hát ebbe definiáltam. Úgy tűnik az Ext ilyenkor átalakítja ez a tömböt egy ún. dockedItem-é, így renderelés után csak ebben érhetők el a gombok, nem is annyira bonyolult módon:

panel.getDockedComponent(x).getComponent(y);

ahol X a dockedItem indexe (ha nincs másik, akkor 0) és Y az elérni kívánt gomb indexe.

read more

Subtitlers.hu – közösségi feliratfordítás

{lang: 'hu'}

Útjára indult a legújabb feliratos oldal. Hogy ez miben más, mint a többi?

  • Nincs telehányva reklámokkal a felület. Sőt, egyelőre egyáltalán nem lesz semmilyen reklám az oldalon. Ahogy időm engedi kiteszek egy támogatás gombot, ha valakinek tetszene a szolgáltatás és megtámogatná az oldal fenntartását
  • Működik! Nem fogsz 404 – Az oldal nem található és hasonló szépségeket kapni. Ha mégis, akkor nagy gáz van :)
  • Használható. Egyszerű, logikus felépítésű felületet terveztem, ami lehetővé teszi, hogy bármilyen céllal jössz is az oldalra, a leggyorsabban elérd azt.
  • Felirat letöltés és feltöltés mellett, egy egészen újszerű szolgáltatást nyújt az oldal. Sok ember fordíthat egyszerre egy feliratot, így egyrészt lehet tehermentesíteni a fordítót, másrészt sokkal gyorsabban elkészülhet egy felirat. Ha 4-5 ember összeáll (és tegyük fel vágják olyan szinten az angolt, hogy használható feliratokat gyártanak), akkor 1-2 óra alatt lelehet fordítani egy feliratot.
Próbáld ki az oldalt és mondd el a véleményed, vagy ha hibát találtál, vagy ha van valami fejlesztési ötleted. Ha tetszik, oszd meg ahol tudod, hogy közösen tudjunk dolgozni a közös jóért :)
És egy link az oldalhoz: http://www.subtitlers.hu
read more

-val, -vel rag generálása szóhoz

{lang: 'hu'}

Összedobtam egy egyszerű függvényt, amivel egy megadott szóhoz -val, -vel ragot lehet képezni (pl. alma -> almával). Egyenlőre javascript-ben van megírva, de kérés alapján php-ra is simán átírható. A tévedés jogát fenntartom, ha találtok olyan esetet, amikor nem jól működik, akkor hozzászólásban várom a szót. (lehetséges, hogy valamelyik speciális magánhangzó páros kimaradt a listából) Tehát a függvény:

UPDATE: kód frissítve, köszönet az észrevételekért és a javítási javaslatokért!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
function addWithTermination(word) {
 
    var vowels = [
        'a', 'á',
        'e', 'é',
        'i', 'í',
        'o', 'ó',
        'ö', 'ő',
        'u', 'ú',
        'ü', 'ű'
        ],
        terminations = {
            'val': ['a', 'ae', 'aé', 'ai', 'aí', 'á', 'ái', 'áí', 'o', 'oi', 'ó', 'u', 'ú'],
            'vel': ['e', 'ei', 'é', 'i', 'í', 'ö', 'ő', 'ü', 'ű']
        },
        specialConsonants = [ 'cs', 'gy', 'sz', 'ty', 'zs' ],
        specialDoubleConsonants = [ 'ccs', 'ggy', 'ssz', 'tty' ],
        exceptions = {
            'val': ['íj', 'híd', 'díj'],
            'vel': []
        },
        lastCharIndex = word.length - 1,
        lastChar = word[lastCharIndex],
        vowelsAsString = vowels.join(''),
        vowelsPattern = new RegExp('[' + vowelsAsString + ']', 'ig'),
        vowelsMatch = word.match(vowelsPattern),
        lastTwoVowels = [],
        lastTwoVowelsAsString, termination;
 
    if (exceptions.val.indexOf(word) !== -1) {
        termination = 'val';
    }
    else if (exceptions.vel.indexOf(word) !== -1) {
        termination = 'vel';
    }
    else if (vowelsMatch.length > 1) {
        /* Több magánhagzó van a szóban */
        lastTwoVowels.push(vowelsMatch[vowelsMatch.length - 2]);
        lastTwoVowels.push(vowelsMatch[vowelsMatch.length - 1]);
        lastTwoVowelsAsString = lastTwoVowels.join('');
 
        if (terminations.val.indexOf(lastTwoVowelsAsString) === -1 && terminations.vel.indexOf(lastTwoVowelsAsString) === -1) { /* A magánhagzó pár nem egy speciális pár */
            termination = terminations.val.indexOf(lastTwoVowels[1]) === -1 ? 'vel' : 'val';
        }
        else {
            /* A magánhagzó pár egy speciális pár */
            termination = terminations.val.indexOf(lastTwoVowelsAsString) === -1 ? 'vel' : 'val';
        }
    }
    else if (vowelsMatch.length === 1) {
        /* Csak egy magánhangzó van a szóban */
        termination = terminations.val.indexOf(vowelsMatch[vowelsMatch.length - 1]) === -1 ? 'vel' : 'val';
    }
    else {
        /* Ilyen szó nincs */
        return word;
    }
 
    if (vowels.indexOf(lastChar) !== -1) {
        if (vowels.indexOf(lastChar) % 2 === 0) {
                /*
                 * Az utolsó karakter magánhangzó és ha
                 * nem ékezetes, akkor ékezetessé kell tenni
                 */
            word = word.substring(0, lastCharIndex) + vowels[vowels.indexOf(lastChar) + 1];
        }
    }
    else {
        if(word[lastCharIndex - 1] !== word[lastCharIndex]) {
            /*
             * Az utolsó karakter mássalhangzó, így
             * ha nem kettős mássalhangzó alapból,
             * akkor megkell kettőzni
             */
            if(specialConsonants.indexOf(word.substr(lastCharIndex - 1))  !== -1 && specialDoubleConsonants.indexOf(word.substr(lastCharIndex - 2)) === -1) {
                /*
                 * Az utolsó két karatkter: 'cs', 'gy', 'sz', 'ty' vagy 'zs',
                 * ezeknél az első karaktert duplázzuk
                 */
 
                word = word.substr(0, lastCharIndex) + word[lastCharIndex - 1] + word[lastCharIndex];
            }
            else if(specialDoubleConsonants.indexOf(word.substr(lastCharIndex - 2)) === -1) {
                word += word[lastCharIndex];
            }
 
        }
 
        /*
         * Mássalhangzóra végződés esetén mindenképp
         * törölni kell a -val, -vel ragból a v-t
         */
        termination = termination.substring(1);
    }
 
    word += termination;
 
    return word;
}
read more

MongoDB: egy tömb (ismeretlen indexű) elemének frissítése

{lang: 'hu'}

Ha egy collection-ben a dokumentumunk egyik propertyje egy tömb, akkor kicsit kacifántosabb egy tömbön belüli elem lekérdezése és frissítése. A lekérdezésre ott van a map/reduce funkció. A frissítésre pedig használhatjuk a már megszokott update függvényt a positional operator-al ötvözve. Böngésztem a netet, de én hasonló példát nem láttam, úgyhogy lássuk! Tegyük fel, hogy a következő struktúránk van a photos collection-ben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
   "userId": 1,
   "albums": {
      "1": {
         albumDefault: 1,
         photos: [{
            photoId: 1,
            photoDescription: "Alma"
            ...
         }, {
            photoId: 2,
            photoDescription: "Körte"
            ...
         }{
            photoId: 3,
            photoDescription: "Barack"
            ...
         }]
      }
   }
}

Ha szeretnénk módosítani pl. a 3-as photoId-vel rendelkező kép leírását, akkor a következő utasítással érhetjük el:

1
2
3
4
5
6
7
8
db.photos.update({ 
   "userId": 1, 
   "albums.1.photos.photoId": 3 
}, { 
   "$set": {
      "albums.1.photos.$.photoDescription": "Szőlő"
   } 
});

És egy megvalósítás php-ben is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$mongo = new Mongo();
$db = $mongo->test_db;
$photos = $db->photos;
$condition = array(
   "userId" => 1, 
   "albums.1.photos.photoId" => 3
);
$fieldToUpdate = array(
   "$set" => array(
      "albums.1.photos.$.photoDescription" => "Szőlő"
   )
);
 
$photos->update($condition, $fieldToUpdate);
read more

MongoDB: hivatkozás egy GridFS-ben tárolt fájlra

{lang: 'hu'}

Tegnap belefutottam egy érdekes problémába a MongoDB-vel kapcsolatban: egy dokumentum property-je ugybár lehet egy másik dokumentumra mutató hivatkozás is, de vajon lehet fájlokra is mutatni így linkkel? Igen! Nekem egy felhasználó profilt kell modelleznem az adatbázisban, viszont a profilképeket nem akartam inline betenni a profil infót tartalmazó dokumentumba (egyrészt a file-okat először is Base64-el encode-olni kellene, ami elég durva méretnövekedést tud okozni, másrészt pedig egy általános keresésnél, ahol nincs megadva mely mezőkre van szükségem egészen letudja lassítani a keresést).

A profil dokumentumok szerkezete így néz ki:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
   "userId":"4e5de5348deb9f622e000215",
   "firstName":"Gabor",
   "lastName":"Szabo",
   ...,
   "pictures":{
      "profilePicture":{
         "small": GridFS Reference,
         "medium": GridFS Reference,
         "big": GridFS Reference
      },
      ...
   },
   ...
}

1. lépés: szúrjuk be a GridFS-be a kívánt profilképet

1
2
3
4
5
$m = new Mongo();
$db = $m->test_db;
$profiles = $db->profiles;
$gridFS = $db->getGridFS();
$gridFS->storeFile("profile_pic.jpg", array("metadata" => array("date" => new MongoDate())));

2. lépés: kérjük le a beszúrt objektumot (az egyszerűség kedvéért a GridFS-ben csak egy kép lesz, de természetesen a find ugyanúgy működik itt is, mint az egyéb collection-ök esetén)

1
2
3
4
5
$m = new Mongo();
$db = $m->test_db;
$profiles = $db->profiles;
$gridFS = $db->getGridFS();
$picture = $gridFS->findOne();

3. lépés: szúrjuk be a profil dokumentumot a profiles collection-be, a lekért kép-re való hivatkozással

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$doc = array(
	"userId"    => "4e5de5348deb9f622e000215",
	"firstName" => "Gabor",
	"lastName"  => "Szabo",
	...
	"pictures"  => array(
		"profilePicture" => array(
			"small"  => MongoDBRef::create($gridFS->getName(), $picture->file['_id']),
			"medium" => MongoDBRef::create($gridFS->getName(), $picture->file['_id']),
			"big"    => MongoDBRef::create($gridFS->getName(), $picture->file['_id'])
		)
	),
	...
);
 
$profiles->insert($doc);

4. lépés: kérjük le a profilban dokumentumban szereplő valamelyik képet (az egyszerűség kedvéért megint feltételezzük, hogy csak egy dokumentumunk van a collection-ben)

1
2
3
4
5
$p = $profiles->findOne();
$smallProfilePicture = MongoDBRef::get($db, $p['pictures']['profilePicture']['small']);
 
/* A fájl tényleges tartalma pedig így kapható meg */
$smallProfilePicture->getBytes();
read more

Apache cache letiltása

{lang: 'hu'}

Fejlesztés közben kitéped a hajad, mert cache-ből kapod a fájlaid és így nem frissül a tartalom? A megoldás egyszerű, egy .htaccess fájlba vagy az apache konfigba tedd be ezt:

EnableSendfile Off
read more