Archivál

Posts Tagged ‘jQuery’

jQueryUI Datepicker lokalizálás

2012.04.30. 4:00 Hozzászólás

A jQueryUI Datepicker minden szempontból annyira praktikus, hogy már szinte minden projektünkben használjuk. Az eredetileg angol nyelven megjelenő naptár vezérlőt nagyon könnyen lehet más nyelvűvé alakítani, mindössze az adott nyelvhez tartozó lokalizációs fájlt kell betöltenünk az oldalunkra, majd át kell kapcsolnunk rá a Datepickert:

$(selector).datepicker($.datepicker.regional['hu']);

De mi van akkor, ha az oldal renderelésekor még nem tudjuk, hogy milyen nyelvre lesz szükségünk? Ilyenkor jöhetnek a dinamikus szkript betöltési módszerek a kb. 1KB-os nyelvi fájlok betöltésére.

Ha sokszor, sokféle nyelven használjuk a dátum vezérlőt, akkor hasznos lehet a kis méretű fájlok külön-külön letöltése helyett egyszerre letölteni az összes nyelv beállításait. Ezen az URL-en található egy ilyen fájl, amiben az összes (?) támogatott nyelv beállításai megtalálhatók:

http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/i18n/jquery-ui-i18n.min.js

Ez egy minimalizált fájl, de a mérete még így is 51KB, azonban ha a webszerveren beállítjuk a tömörítést, akkor mindössze 11KB marad.

 

Technorati-címkék: ,,
Kategóriák:Webfejlesztés Címkék:,

Ajax hívásnál 401 Unauthorized

Érdekes hibával találkoztam a héten. Adott egy jQuery-vel meghívott WebMethod, ahonnan a HTTP kérések kiválóan kimennek, de a válasz mindig ez:

{ "Message":"Authentication failed.",
  "StackTrace":null,
  "ExceptionType":"System.InvalidOperationException" }

Különlegességként a válaszban még érkezik egy jsonerror: true fejléc sor is.

Amit ilyenkor célszerű ellenőrizni:

  • Jogosultságok a web.configban ne tiltsák a hozzáférést.
  • Ha esetleg kell Session is, akkor a szerver oldalon a WebMethod attribútumnál legyen beállítva az EnableSession=true tulajdonság.
  • Ha a szerver oldali metódus ASPX-ben van, akkor legyen static.
  • És a ráadás: az ASMX fájlban lévő @WebService direktíva Class tulajdonsága az .ASMX.CS fájlban lévő névtérre és osztályra mutasson. Ez utóbbi azért huncut, mert a Solution Explorerben az .asmx fájlra kattintva az .asmx.cs nyílik meg, nincs fordítási hibaüzenet és a futás idejű hibából sem derül ki, hogy ez a gond.

 

Technorati-címkék: ,,,,
Kategóriák:Webfejlesztés Címkék:, , ,

JavaScript hibakeresés 1×1

Véleményem szerint ma már nem létezik “szerver oldali webprogramozó”, hiszen szinte minden weboldalhoz tartozik már szerver és kliens oldali logika is. A kliens oldali JavaScript és jQuery kódok debuggolása elsőre nagyon idegen feladatnak tűnhet, de valójában egyáltalán nem ördöngösség és szerencsére már kiváló eszközök is vannak hozzá. Az alábbi videóban a Firebug, a FireQuery és a Visual Studio 2010 JavaScript debuggolási lehetőségei közül a leggyakrabban használtak kerülnek terítékre:

Teljes képernyős nézet, 720p felbontás ajánlott.

 

ASP.NET MVC remote validation

2011.10.14. 8:20 Hozzászólás

A model validation az egyik kedvencem az ASP.NET MVC-ben. Egy helyre kerül minden, ami a validáláshoz kell, ráadásul a jQuery validationnek köszönhetően a beépített “validátorok” nagyon jól működnek kliens oldalon is.

Legyen mondjuk egy klasszikus Person modell osztályunk, amire könnyen felaggathatom a validálási szabályokat leíró attribútumokat:

public class Person
{
    [DisplayName( "E-mail cím:" )]
    [Required( ErrorMessage = "Az e-mail cím megadása kötelező! ")]
    public string Email { get; set; }

    [DisplayName( "Felhasználónév:" )]
    [Required( ErrorMessage = "A felhasználónév megadása kötelező! " )]
    public string UserName { get; set; }

    [DisplayName( "Jelszó:" )]
    [Required( ErrorMessage = "A jelszó megadása kötelező! " )]
    public string Password { get; set; }
}

A view-ba pedig csak @Html.ValidationMessageFor hívások kellenek a hibaüzenetek megjelenítéséhez (amiket egyébként a VS le is generál magától):

@using( Html.BeginForm() )
{
    @Html.ValidationSummary( true )
    <fieldset>
        <legend>Regisztráció</legend>
        <div class="editor-label">
            @Html.LabelFor( model => model.Email )
        </div>
        <div class="editor-field">
            @Html.EditorFor( model => model.Email )
            @Html.ValidationMessageFor( model => model.Email )
        </div>
        <div class="editor-label">
            @Html.LabelFor( model => model.UserName )
        </div>
        <div class="editor-field">
            @Html.EditorFor( model => model.UserName )
            @Html.ValidationMessageFor( model => model.UserName )
        </div>
        <div class="editor-label">
            @Html.LabelFor( model => model.Password )
        </div>
        <div class="editor-field">
            @Html.EditorFor( model => model.Password )
            @Html.ValidationMessageFor( model => model.Password )
        </div>
        <p>
            <input type="submit" value="Mehet" />
        </p>
    </fieldset>
}

A helyzet akkor kezd bonyolódni, amikor kliens oldalon szeretnénk validálni, de az input ellenőrzési logika vagy a hozzá szükséges egyéb adatok szerver oldalon vannak, például egy adatbázisban. Még kellemetlenebb a helyzet, ha ráadásul nem is egyetlen mező értékét kell ellenőriznünk, hanem több adat együttállását kell vizsgálnunk. Ezt megoldhatnánk egy postback után a controllerben, de sokkal felhasználóbarátabb, ha Ajaxosan oldjuk meg, hiszen így már az űrlap kitöltése közben tudjuk figyelmeztetni a felhasználót, hogy javítsa ki a beírt értékeket. Szerencsére erre a problémára van közvetlen megoldás az ASP.NET MVC-ben, úgy hívják, hogy remote validation. Így kell beizzítani:

A modellben adjunk egy Remote attribútumot a validálandó mezőhöz:

[Remote( "ValidateUserNameAndEmail", "Home", AdditionalFields = "Email" )]
public string UserName { get; set; }

Itt meg kell adnunk, hogy melyik controller action lesz az Ajax hívás szerver oldali végpontja. Ha több mező értékére van szükségünk szerver oldalon, akkor használhatjuk az AdditionalFields paramétert. A fenti példában a validálás akkor fog megtörténni, amikor a UserName mező értéke megváltozik és a szerverhez el fog jutni az Email mező értéke is, az esetleges hibaüzenet pedig a UserName mező mellett fog megjelenni. Szerencsére semmi akadálya annak, hogy ugyanezt az attribútumot ráakasszuk az Email mezőre is, AdditionParameterkent a UserName mezőt adva meg.

Már csak a hivatkozott controller actiont kell megírnunk, például így:

[OutputCache( NoStore = true, Location = OutputCacheLocation.None )]
public JsonResult ValidateUserNameAndEmail( string userName, string email )
{
    return this.IsValid( userName, email ) ? 
        this.Json( true, JsonRequestBehavior.AllowGet ) : 
        this.Json( "Ezzel a névvel és e-mail címmel már létezik regisztráció!", 
            JsonRequestBehavior.AllowGet );
}

A valódi ellenőrző logikát áttettem egy IsValid függvénybe, hogy itt ne zavarjon. A lényeg:

  • Klasszikus controller action azokkal a paraméterekkel, amiket ellenőrizni szeretnénk. Ha van a modellben AdditionalFields, akkor mindet.
  • Válaszként egy JsonResult típussal kell visszatérnünk.
  • Ha az adat helyes, akkor a válasz true, ha hibás, akkor a hibaüzenet.
  • Meg kell adni a JsonRequestBehavior.AllowGet paramétert, anélkül nem fog menni.
  • Célszerű az OutputCache-t kikapcsolni, hogy a böngésző ne gyorsítótárazza a választ.

A hibaüzenet a Html.ValidationMessageFor helyén fog megjelenni, tehát a view-n nem kell változtatnunk. Ha nem a Studio generálta a markupot, hanem mi írtuk, akkor arra érdemes figyelni, hogy legyen benne Html.BeginForm, mezei <form> elemre tapasztalataim szerint nem működik.

Mindössze ennyi, az Ajaxos bűvészkedést az ASP.NET megcsinálja helyettünk. Íme az eredmény:

aspnet-mvc-remote-validation

Akit szeretné lerántani a leplet a varázslatról, az nézze meg a generált markupban a data-val-remote- attribútumokat és figyelje meg a HTTP forgalmat például Fiddlerrel. Érdemes!

 

Technorati-címkék: ,,,,,
Kategóriák:Webfejlesztés Címkék:, , , , ,

Golyóálló Ajax hívások

Korábban írtam már arról, hogy nagyon egyszerűen tudunk ASP.NET-es page method-okat hívni jQuery segítségével. No, de mi van akkor, ha valamilyen nem várt hiba történik közben?

Nézzük lépésről lépésre, kezdjük először azzal, hogy hogyan is megy ez. Először is legyen egy link, ami elindítja az Ajax hívást, és egy span, ami majd megjeleníti az eredményt:

  <a href="#" id="simpleLink">Egyszerű Ajax hívás</a>
  <span id="result"></span>

Legyen egy WebMethod az oldalon belül, amit ajaxosan meg akarunk hívni a linkre kattintáskor:

  [WebMethod]
  public static string SayHello( string name )
  {
    return "Hello " + name;
  }

Az Ajax híváshoz persze jQuery-t használunk, szerencsére így nagyon rövid a JavaScript kód:

  $("#simpleLink").click(function (e) {
    e.preventDefault();

    $.ajax({
      type: "POST",
      url: "Default.aspx/SayHello",
      data: "{ 'name':'World' }",
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      success: function (data) {
        $("#result").html(data.d);
      }
    });
  });

Hol lehet ezzel probléma? Néhány tipikus eset:

  • Bármiféle alacsonyszintű (hálózati) hiba keletkezik.
  • A szerver oldali kódból kivétel röppen a kliensre.
  • Lejár a felhasználó login sessionje, ezért az Ajax hívás authentikációs hibával száll el, mert nem jut el a szerver oldali végpontig.
  • Lejár a felhasználó munkamenete, ezért a szerver oldali kód érvénytelen Session értékekkel dolgozik.

Ezek között van könnyebb és nehezebb eset. Az alacsonyszintű hibákat lehet kezelni egy error callbackben kliens oldalon, szerencsére a jQuery támogatja.

A szerver oldalon keletkező kivétel már rosszabb, mert ennyire barátságos válaszból kell dolgoznia a kliensnek, ami egy HTTP 500 Internal Server Error társaságában jön vissza:

  {
    "Message":"Baj van!",
    "StackTrace":"   at _Default.SayHello(String name) 
       in w:\\System\\Desktop\\AjaxWrapperSample\\Default.aspx.cs:line 14",
    "ExceptionType":"System.InvalidOperationException"
  }

A példában itt egy “nem várt” eset szerepel (hiszen az InvalidOperationException általában erre utal), de mihez kezdünk akkor, ha az üzleti logikánk is kivétellel jelzi, ha valamit nem sikerült végrehajtani? Például mert a felhasználónak nincs hozzá jogosultsága, vagy megváltozott az üzleti objektum állapota, karbantartás alatt van az alkalmazásszerver stb.

A lejárt login session kifejezetten kellemetlen, mert klasszikus HTTP 200 OK tud visszajönni, csak éppen a tartalomban nem a kért adatokat küldi vissza a szerver, hanem a bejelentkező oldalunk HTML markupját. Talán erre számít legkevésbé az ember.

Ezeket természetesen mind lehet kezelni szerver és kliens oldalon is, a nehézséget az jelenti, hogy ezt minden egyes Ajax hívásnál meg kell tennünk kliens és szerver oldalon is. Célszerű lenne olyan megoldást találnunk, ami nem igényli az összes WebMethodunk és az összes kliens oldali hívásunk szétbarmolását, hanem központilag tudjuk valahogy kezelni a hibákat. És itt jön be a képbe az a szemérmetlenül kellemetlen tény, hogy Ajax hívások esetén az ASP.NET klasszikus központi eseménykezelői (pl. Application_Error) nem hívódnak meg…

Az alábbi megoldást az egyik projektünkben használjuk és eddig bevált. A módszer lényege, hogy az eredeti kódot becsomagoljuk és a csomagolás feladata a részletek elrejtése mind kliens, mind szerver oldalon.

Első lépésként definiáltuk az alábbi osztályt:

  public class AjaxResult<TResult>
  {
    public bool Success { get; set; }
    public TResult Value { get; set; }
    public string Error { get; set; }
  }

Ennek az osztálynak a feladata, hogy burkolja az eredeti választ a Value paraméterben és további információkat csapjon hozzá, amit a kliens felhasználhat az egyedi hibakezeléshez. Itt a példában csak két paramétert vettem fel, a Success jelzi, ha a hívás szerver oldalon nem okozott kivételt, az Error pedig az esetleges hibaüzenetet (ezeket persze lehetne egyben is, de a bool és a string külön nekem szimpatikusabb).

A következő feladat a szerver oldali csomagolás elkészítése olyan módon, hogy az eredeti kódra a legkisebb hatással legyen. Erre az alábbi megoldás született:

  public static class AjaxWrapper
  {
    public static AjaxResult<TResult> Execute<TResult>( Func<TResult> body )
    {
      try
      {
        // Inicializálás, szerver konfigurálás itt...

        return new AjaxResult<TResult>
        {
          Success = true, 
          Value = body()
        };
      }
      catch( Exception ex )
      {
        return new AjaxResult<TResult>
        {
          Success = false,
          Error = ex.GetType().Name
        };
      }
    }
  } 

Oké, a Func miatt elsőre talán nem egyértelmű, hogy mi történik, ezért gyorsan megmutatom, hogyan kell használni és máris világos lesz a jelentése. A fenti SayHello metódusból ez lett:

  [WebMethod]
  public static AjaxResult<string> SayHelloSafe( string name )
  {
    return AjaxWrapper.Execute( () =>
    {
      return "Hello " + name;
    });
  }

A kód lényegi része tehát megmaradt, mindössze egy AjaxWrapper.Execute hívást kell köré csapni. Siker esetén a lényegi rész eredménye bekerül a Value tulajdonságba, hiba esetén pedig a kivétel típusa kerül az Error tulajdonságba. Ezzel elértük azt, hogy a kódunkban keletkező összes szerver oldali hibát elkapjuk és barátságos formában juttatjuk a kliensre.

Már csak ki kell csomagolnunk a választ kliens oldalon, amivel egyúttal a klasszikus d tulajdonságtól is megszabadulhatunk. Ehhez jó lesz az alábbi JavaScript függvény:

  function myAjax( url, params, successCallback, errorCallback ) {
    $.ajax({
      type: "POST",
      url: url,
      data: params,
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      success: function (response, status, xhr) {
        if (response.d.Success) {
          successCallback(response.d.Value, status, xhr);
        }
        else {
          errorCallback(response.d.Error, status, xhr);
        }
      },
      error: function (xhr, status, error) {
        if (xhr.status === 401) {
          alert("Lejárt a munkameneted, lépj be újra!");
          window.location.href = "Login.aspx";
          return;
        }

        errorCallback(xhr, status, error);
      }
    });            
  }

Itt egyúttal megoldhatjuk a lejárt login session esetét is. Ha szerver oldalon az AjaxWrapper.Execute metódusban kitalálunk egy módszert a lejárt Session kezelésére, akkor ezt az esetet is kezelhetjük itt központilag.

Végezetül csak arra kell figyelnünk, hogy mostantól a $ajax helyett mindenhol ezt a myAjax függvényt használjuk:

  myAjax(
    "Default.aspx/SayHelloSafe",
    "{ 'name':'World' }",
    function (response) {
        $("#result").html(response);
    },
    function (response) {
        $("#result").html('Gáz van: ' + response);
    }
  );

Kicsit egyszerűsítettem a kódon, élesben egy kicsit bonyolultabb, de ez a lényeg. A teljes forráskód letölthető az MSDN Kompetencia Központ oldaláról.

Ti hogyan kezelitek ezeket a kivételesen kellemetlen eseteket?

 

Technorati-címkék: ,,,,

Globalizálás és lokalizálás JavaScriptben

2011.08.28. 4:00 Hozzászólás

Ahogy a webalkalmazásaink logikájának egyre jelentősebb része költözik a kliens oldalra, úgy egyre gyakrabban merül fel az igény, hogy lokalizáljunk és globalizáljunk JavaScriptben. Például egy Ajax hívás nyers JSON adatokat ad vissza, de persze az átküldött Date objektumot már a felhasználó nyelvi beállításainak megfelelően kellene sztringgé alakítanunk megjelenítés előtt. Vagy éppen egy alert ablakot kell feldobnunk, természetesen olyan nyelven, amelyen ért a felhasználó.

A problémára több megoldás létezik, nekem a Microsoft által tavaly bejelentett jQuery Globalization Plugin tűnik legszimpatikusabbnak, mégpedig azért, mert nagyon közel áll a szerver oldalon megszokott CultureInfo képességekhez. Sajnos a plugin elsőre elég barátságtalannak tűnik, több ok miatt:

1. A bejelentés óta nem sokat írt róla sem a Microsoft, sem pedig a jQuery csapat, de szerencsére ez nem azt jelenti, hogy egy újabb ígéretes fejlesztés került a kukába, ugyanis a jQuery csapatnak komoly tervei vannak ezzel a komponenssel.

2. Nehéz megtalálni az aktuális verziót, mert időközben átnevezték a projektet. Már nem jQuery Globalization Pluginnek hívják, hanem egyszerűen csak jQuery Globalize és itt található: https://github.com/jquery/globalize. “Globalize certianly needs some polishing and bug fixing, but the API is now pretty stable, so you should give it a try.”

3. A nevében a “jQuery” félrevezető. Szerencsére már nem hívják “plugin”-nak, ugyanis nem plugin. Ez egy önálló JavaScript osztálykönyvtár hasznos függvényekkel, nem kell hozzá se $, se selector.

Mit tud?

  • Ismeri 350 kultúra paramétereit, méghozzá a .NET Framework CultureInfo adatai alapján, de persze a lista bővíthető. Számformátumok, dátum formátumok, naptár információk stb.
  • Számok és dátumok formázása a megadott kultúra szerint. A sok formázási lehetőséget legegyszerűbben a példák között található examples/browser/index.html fájl futtatásával lehet áttekinteni.
  • Lokalizált sztringek definiálása és felolvasása.
  • Egész számok, törtszámok és dátumok parszolása sztringből.

A rövid, de használható dokumentáció megtalálható itt: https://github.com/jquery/globalize/blob/master/README.md

Bár a jelenlegi verziószáma 0.1.0a1 (ez vajon mennyivel több, mint a 0.0?) és van néhány nyitott issue, a tapasztalataink alapján már jól működik, merjük is élesben használni.

Ti mit használtok kliens oldali globalizálásra és lokalizálásra?

 

Kategóriák:Webfejlesztés Címkék:,

ASP.NET-es képfeltöltő CLEditorhoz

Nagyon sok JavaScriptes WYSIWYG editor létezik, nekem az egyik kedvencem a CLEditor. Nem tud sokat, nem is tökéletes, de kicsi, egyszerű, pluginekkel bővíthető és jQuery alapú. Az egész editor 4 fájlból áll és mindössze 9kb, amiért ezt kapjuk:

cleditor-demo

Nem is beszélve arról, hogy gyakorlatilag ingyenesen használható a MIT és a GPLv2 licencek értelmében. Egy próbát mindenképp megér, ami a fájlok bemásolása után mindössze ennyi:

<head runat="server">
  <link href="Scripts/CLEditor/jquery.cleditor.css" rel="stylesheet" type="text/css" />
  <script src="Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
  <script src="Scripts/CLEditor/jquery.cleditor.js" type="text/javascript"></script>

  <script type="text/javascript">
    $(function () {
      $('#txtContent').cleditor();
    });
  </script>
</head>

<body>
  <form id="form1" runat="server">
    <div>
      <asp:TextBox ID="txtContent" runat="server" 
                   ClientIDMode="Static" TextMode="MultiLine" />
    </div>
  </form>
</body>

Mint sok más editor, sajnos alapból ez sem tud képfeltöltést, csak képbeszúrást, ami különösen nem is meglepő, hiszen a fájlfeltöltéshez szerver oldali komponens is kell. PHP-s megoldást találtam, de nekem természetesen ASP.NET-es kellett, hát csináltam egyet.

A pluginezés szerencsére nagyon egyszerű, gyakorlatilag egy új gombot kell regisztrálni:

$.cleditor.buttons.imageUpload = {
    name: "imageUpload",
    image: "imageUpload.png",
    title: "Upload and insert image",
    command: "inserthtml",
    buttonClick: onImageUploadButtonClick
};

Majd ezt a gombot beszúrni az eszköztárra, például a beépített képbeszúró gomb (“image”) elé:

$.cleditor.defaultOptions.controls = 
  $.cleditor.defaultOptions.controls.replace("image", "imageUpload image");

Máris van egy gombunk, és ha a felhasználó rákattint, meghívódik az onImageUploadButtonClick függvényünk. Itt egy jQueryUI-os dialog ablakot szeretnénk feldobni, amiben egy iframe jeleníti meg az ASP.NET-es feltöltő oldalt. Ezt így alapozhatjuk meg a markupban:

<div id="dialog" style="display: none;">
    <iframe src="ImageUploadPopup.aspx" frameborder="0"></iframe>
</div>

Ha ez megvan, akkor máris írhatjuk a JavaScript kódot a popup megjelenítésére:

  function onImageUploadButtonClick(e, data) {
    // Open a new popup dialog.
    $("#dialog").dialog({
        autoOpen: true,
        modal: true,
        width: '500',
        position: 'auto',
        title: 'Insert image',
        buttons:
        [
            {
                text: "Insert",
                click: function () {
                    $(this).dialog('close');
                    onImageUploadPopupClose(data);
                }
            },
            {
                text: "Cancel",
                click: function () {
                    $(this).dialog('close');
                }
            }
        ]
    });

    // Ez kell, hogy az IE az editorba szúrja be a képet,
    // ne kedve szerint valami meglepő helyre az oldalon.
    data.editor.focus();

    // A false azt jelzi, hogy a gomb funkcióját teljes egészében mi
    // valósítjuk meg, ne a gomb deklarációnál megadott command hajtódjon végre.
    return false;
  }

A végén lévő két sortól eltekintve ebben semmi extra nincs, klasszikus jQueryUI dialog. A felugró ablakba az ImageUploadPopup.aspx fog betöltődni, ami a példa kedvéért igen egyszerű:

<asp:FileUpload runat="server" ID="fupImage" />
<asp:Button ID="btnUpload" runat="server" 
            onclick="btnUpload_Click" Text="Upload" />
<asp:Label ID="lblResult" runat="server" />
<asp:HiddenField ID="hfSelectedImageUrl" runat="server" ClientIDMode="Static" />

A fájlt az Upload gomb megnyomására töltjük fel, majd a Labelben tájékoztatjuk a felhasználót az eredményről. A rejtett mezőt arra használjuk, hogy beleírjuk azt az URL-t, amit majd az editorba be kell szúrni. A gomb eseménykezelője:

protected void btnUpload_Click( object sender, EventArgs e )
{
  // Fájl mentése a diszkre.
  // VIGYÁZAT: demó kód, input validálás hiányzik!
  string folder = this.Server.MapPath( "~/Upload" );
  string target = Path.Combine( folder, this.fupImage.FileName );
  this.fupImage.SaveAs( target );

  // Felhasználó tájékoztatása.
  this.lblResult.Text = String.Format( CultureInfo.InvarianCulture, 
                                     "{0} feltöltve!", this.fupImage.FileName );

  // Beszúrandó URL mentése a rejtett mezőbe.
  this.hfSelectedImageUrl.Value = "Upload/" + this.fupImage.FileName;
}

Amikor a felhasználó az Insert gombra kattintva bezárja a dialógusablakot, akkor meg fog hívódni az onImageUploadPopupClose függvényünk. Itt kiolvassuk a rejtett mező tartalmát, gyártunk belőle egy img elemet és megkérjük az editort, hogy szúrja be a szövegbe:

  function onImageUploadPopupClose(data) 
  {
    var strSelectedImageUrl = 
      $("#dialog").find("iframe").contents().find("#hfSelectedImageUrl").val();

    var editor = data.editor;

    var html = "<img src='" + strSelectedImageUrl + "' />";
    editor.execCommand(data.command, html, null, data.button);

    editor.hidePopups();
    editor.focus();
  }

 

Leírni bonyolultabb, mint megcsinálni, de még egyszerűbb a teljes forráskódot letölteni innen.

 

Technorati-címkék: ,,,,
Kategóriák:Webfejlesztés Címkék:, ,

HTML 5 custom data attributes

A HTML 5 szabványba foglalt egyik legkedvesebb részem a custom data attribute lehetősége. Egyrészt azért tetszik, mert nagyon régóta fájó problémát old meg, másrészt mert nem kell megvárni hozzá a HTML 5 szabvány elkészültét, már ma is használható, a korábbi böngészők is elviselik.

Röviden a custom data attributes arra jó, hogy tetszőleges, nem látható információt ágyazzunk be kulturált módon a HTML markupba. Ehhez nem kell más tennünk, mint egy data- kezdetű attribútumot biggyesztenünk a kiszemelt HTML elemhez. Például így:

  <span data-rendezo="Michael Bay">Transformers</span>

Ha erre az adatra később szükségünk van JavaScriptben, akkor akár az element.dataset tulajdonságon keresztül, akár jQuery-vel a data() metóduson keresztül elérhetjük:

  alert( $('span').data('rendezo') );    // --> Michael Bay

Persze a jQuery támogatja az értékek írását, törlését és hozzáadását is. Sőt, akár összetett objektumokat is tehetünk ide, természetesen JSON formában (a tulajdonságok neveit idézőjelbe kell tenni):

  <span id="tr"
    data-film='{ "rendezo": "Michael Bay", "ev": 2007, "moziban": true }'>
    Transformers
  </span>

Kiolvasni nagyon egyszerű:

  var f = $("#tr").data('film');

És ahogy Firebugban is látszik, egy összetett objektumot kapunk vissza, méghozzá nem csak stringekkel, hanem ha lehet, típusokkal (Boolean, Number):

dataAttribute-Firebug

Sokkal jobb, mint JavaScriptbe írni a szerver oldalon előálló adatokat vagy hidden fieldeket generálni, nem?

Ez az a pont, ahol az ember úgy érzi, hogy ennél egyszerűbb és jobb dolog nincs a világon. Csakhogy a specifikáció nagyon pontosan definiálja, hogy hogyan kell kezelni a nagybetűs és a kötőjeles attribútumokat, ami nagyon érdekes hibákat tud eredményezni. Vegyük például ezt:

  <p data-productId="22">...</p>

Talán meglepő, de ez bizony undefined a javából:

  alert( $("p").data("productId") );

Helyesen:

  alert( $("p").data("productid") );

Ez nem bug, főként nem a szerver oldali keretrendszer hibája, hanem feature: úgy működik, ahogy a specifikáció előírja.

A jQuery próbál segíteni a programozói bénaságokon és gyakran többféleképpen is elérhetővé teszi ugyanazt az adatot. Például íme a markup:

  <p data-Id="22">...</p>

Ebből az Id két módon is elérhető:

  $("p").data("id")
  $("p").data("Id")

A Studio is tudja, mi a helyes, mert a Format Document vagy Format Selection parancs kiadásakor kisbetűsre alakítja ezeket az attribútumokat.

Mindenképp érdemes elolvasni azt a pár mondatot a specifikációban, ami erről szól (3.2.3.8 fejezet) és csak akkor használni ezt a lehetőséget, ha értjük is.

Keresztkérdés! Íme a markup:

  <p data-egy="1" 
     data-Ketto="2" 
     data-haromHarom="3" 
     data-Negy-negy="4" 
     data-ot-ot="5" 
     data-hat-Hat="6">...</p>

Milyen tulajdonságai lesznek az alábbi sor után az adat objektumnak?

  var adat = $("p").data();

Íme a megoldás (a szürke kosz egy mini kép, kattints rá a teljes mérethez): Kattints ide a megoldás megtekintéséhez!

 

Technorati-címkék: ,,
Kategóriák:Webfejlesztés Címkék:, ,

WCF és REST – ahol mindenre van URI

Az alkalmazásintegráció területén a SOAP mellett egyre nagyobb szerepet kapnak a REST alapú megoldások. Mert kicsi, egyszerű, gyors. Egyszóval fapados. Nem csak az elkésztése, hanem a meghívása is, ami különösen akkor érdekes, ha a klienseink butábbak az átlagnál, például Ajaxos weboldalak vagy épp telefonok.

Ezt a területet a Microsoft már évekkel ezelőtt célba vette, és kiadta hozzá a WCF REST Starter Kitet. Még sosem hallottál róla? Hát valóban nem ez lett a világ leghíresebb terméke, de legalább elindította a céget egy olyan irányba, amelynek komoly mérföldköve lett a .NET4 és a héten a MIX’11 konferencián bejelentett WCF Web API.

A WCF Web API a WCF Futures csomagban érhető el, amely a következő területekre fókuszál:

  • REST – ez a WCF Web API
  • Kliensek – Ajax, jQuery, Silverlight, telefon
  • Felhő
  • Egyszerűsítés

Ezek közül a MIX-en két területtel kapcsolatban jelent meg újdonság.

1. A REST területen elérhetővé vált a WCF Web API Preview 4 verziója. Ennek az a célja, hogy az alkalmazásaink funkcióit egyszerűen nyithassuk meg HTTP felett a REST alapelveit követve. Itt egy olyan architektúrát kell elképzelni, ahol minden a HTTP-re van kihegyezve:

WCF-Web-API

2. A kliensek területén megjelent a RIA/JS, ami gyakorlatilag közvetlen WCF támogatást jelent a jQuery-hez:

WCF-jQuery

Ez még elég gyerekcipőben jár, de a BigShelf példa alkalmazáson már érezhető, hogy a $.dataSource és a DataLink jQuery pluginek mennyire egyszerűsítik a megírandó kliens oldali kódot.

Aki web API fejlesztéssel foglalkozik, annak mindenképp érdemes megnéznie az újdonságokat, mert a jelek szerint a REST a jövő.

 

Technorati-címkék: ,,
Kategóriák:Webfejlesztés Címkék:, , ,

OData sorozat 3: a publikált adatok elérése jQuery-ből

Miután a sorozat első epizódjában megnéztük, milyen egyszerű közzétenni az adatokat OData protokollon keresztül, majd a második részben ezeket az adatokat Excel PowerPivot-n keresztül értük el, ebben a harmadik epizódban egy programozottabb megoldást mutatok be.

Ezúttal arra látunk példát, hogy JavaScriptből jQuery segítségével hogyan lehet letölteni az adatokat és hogyan lehet őket egyszerűen megjeleníteni egy sima HTML oldalon a jQuery Templates plug-in segítségével:

720p, teljes képernyő ajánlott

Egyszerűbb, mint gondoltad, nem?

 

Technorati-címkék: ,,,,
Kategóriák:Adatkezelés Címkék:, , , ,
Follow

Get every new post delivered to your Inbox.

Join 34 other followers