📜 ⬆️ ⬇️

Cache + jQuery. Fast start

The article shows how jQuery can be used to work with the Caché database, which results in a simple functionality for inserting and deleting data in the ajax web application.

It is assumed that the reader has an average level of knowledge of HTML, CSS and Javascript and has minimal experience with Intersystems Cache. Download the latest version of Caché here . Initial experience with Caché can be found here .


Why do you need jQuery in a CSP application?

CSP (Zen) is the basic technology offered by Caché to quickly create ajax web applications that work with the Caché database.
How can jQuery help your CSP (ZEN) application?
1. Convenient access to any element of the html page

The jQuery framework allows you to access elements using the CSS selector syntax, implementing this functionality in the most preferred way for each browser.
2. Cross-browser compatibility

Cross-browser compatibility is an essential requirement for a modern Web application. The developers of the framework claim that the code developed using jQuery will function uniformly in browsers - IE 6.0+, FF 3.6+, Safari 5.0+, Opera, Chrome.
Plugins

jQuery provides a convenient way to extend its functionality with plugins. Since the creation of the framework (in 2006), quite a few of them have been written. Special mention deserves the client interface library jQueryUI .
')
How to connect jQuery to your CSP (ZEN) page?


Download a compressed version of the library from the official site , place it in the CSP directory of the application, point to the csp (zen) page that the jQuery file of a specific version will be used.

For example:
CSP
<script type="text/javascript" src="jquery-1.7.1.min.js"></script> 

ZEN

Parameter JSINCLUDES As STRING="jquery-1.7.1.min.js"

CLS

 w "<script type='text/javascript' src='jquery-1.7.1.min.js'></script>" 

CSP, ZEN and CLS - three approaches to creating server pages in Caché.
When compiling, each CSP page is converted into a standard class Cache — a successor of the% CSP.Page class — CSP. From here follows the second method - code-oriented, it assumes the initial development of the page using the classes Cache, the heirs of the% CSP.Page class - CLS approach. Read more about the differences here .
The third method — development using Zen — combines these two methods — using both Zen tags and object code. In the examples given, the designations CSP, CLS, ZEN, denote the methods used to work out the page that was used to create the example.

For Internet applications, the preferred method would be to use content delivery networks (CDN). In this case, the jQuery file will be located on the servers of one of the listed networks . CDN connection example:
 CSP: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> ZEN: Parameter JSINCLUDES As STRING="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"; CLS: &html< <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> > 


Using jQuery


The most used jQuery function is called jQuery (), but its most commonly used synonym is $ (). The result of this function will depend on the type and number of arguments passed. The main options for calling this function:
1. The following string is passed as an argument:
The method will try to interpret the string either as a jQuery selector (CSS) or as html code:
 $( "div#1973" ) //   div   1973 $( ".doc td" ) //   <td>        doc $( "<div>Write less, do more</div>" ) // *   

2. As an argument, the page element is passed:
 $( document.body ) //  body  «»   jQuery $( document.forms[0] ) //      «»   jQuery 

3. The function is passed as an argument:
 function loadHandler() { alert( " " ); } $( loadHandler ); 
or anonymous function:
 $( function (){ alert( " " ); } ); 

The passed function will be executed upon the document loading event. Such a call can be used instead of:
 <body onload="loadHandler"> 

In addition to searching for elements on the page, jQuery contains methods for manipulating them. List of frequently used functions:
 html()    html- . val()       (input,select) attr()       append(), appendTo()    ,       remove()   bind(), unbind() ,   .     bind()    click(), keypress(), hover()  .. addClass(), removeClass(), toggleClass() , ,  ()  css()      show(), hide() ,   parents(),parent() children()      

* Full list of features can be found here.

It is necessary to note some rules implemented in jQuery:
- the result of the query is packaged in a jQuery object;
- Most functions return call context.

Compliance with these rules makes the code "unobtrusive" and allows the use of "chained" syntax. Sample code using jQuery that searches for an element and replaces its value:

 <script type="text/javascript" src="jquery-1.7.1.min.js"></script> <script type="text/javascript"> $(function(){ $( ".age38" ) //      age38 .val( "Write less, do more" ) //      .css( "font-size", "110%" ) //      .click( function(){ $(this).val(""); } ) //    //  «»     . }); </script> 


"Unobtrusiveness" is that for the above code, if there are no elements on the page with the age38 class, no execution error occurs and the code execution is not interrupted

Below is an example, javascript with similar functionality, but without jQuery
 <script type="text/javascript"> //          //  ""   window var page={}; // window.page=new Object(); //        //       page.getByClass=(document.getElementsByClassName) ? function(clnm){ // IE9, FireFox 3, Opera 9.5, Safari 3.1    return document.getElementsByClassName(clnm); } : function(clnm){ /// IE 6.0-IE 8.0    var arr=[]; ///        ///      var scanDown=function(obj,handler){ for (var child=obj.firstChild;child;child=child.nextSibling){ if (typeof(handler)=="function") handler(child); scanDown(child,handler); } }; ///       ///          var rgxp=new RegExp("(\\s|^)" + clnm + "(\\s|$)"); ///   var classSelect=function( obj ){ if ( ( !obj ) || ( !obj.className )) return; var cls=obj.className; if (!cls.match( rgxp )) return; arr[arr.length]=obj; /// -  }; scanDown( document, classSelect ); //  return arr; } ///  “”    page.bind=(page.ie)? function(obj,evt,func){ obj.attachEvent("on"+evt,func); } : function(obj,evt,func){ obj.addEventListener(evt,func); }; ///      page.main=function(obj){ if (!obj) return; if (obj.nodeType!=1) return; //     obj.value="Write less, do more"; var FS="110%"; if (obj.style) { obj.style.fontSize=FS; } else { obj.style="font-size:"+FS; } page.bind(obj,"click",function(){ obj.value=""; }); }; ///    page.bind( window, "load", function() { var arr=page.getByClass("age38"); //  for (var i in arr){ page.main(arr[i]); //    } }); </script> 

The resulting code is smaller than the jQuery library, but not as versatile and requires a lot of effort from the developer to create and maintain.

Cache + jQuery

Using jQuery on a CSP page

Consider a small example of implementing a chat with minimal functionality and the following interface:
image

Features of the example:
- the interface is completely configured using jQuery
- asynchronous calls to the #call () # server are used, which return a response through a function call on the client
- data is stored in the global

Page source:
 <!DOCTYPE html> <html><head><title> jqChaté </title> <style type="text/css">.msg span {padding: 0px 0px 0px 5px}</style> </head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript"> $( function(){ var USERNAME="#($USERNAME)#" //    Cache , box=$( "<div/>" ).css("overflow","auto") // ,   .css("border","1px solid #ccc").width( 340 ).height( 280 ) // .appendTo( $(document.body) ) //    ; box.parent() //     body //  body input,      .append( $("<input />").css( "width",200 ) .attr("maxlength",50).before( USERNAME+": ") ) .append( //  $("<button/>").text( "Send" ) //     .click( function(){ //    #call(..Add($(this).prev().val()))#; //    (input) $("input").val("").focus(); //textbox ,      }) ); var drawMsg=function(/*[id,time,user,msg]*/ array ){ //  var USER=2, MSG=3, SOFT="#999", BRIGHT="#339" // , msg = $( "<div><span>" + array.join("</span><span>") + "</span></div>") //html  .appendTo( box ).hide() //   -    .addClass("msg") //  .children(":first").hide() //id -   .next().css("color", SOFT) //time //  .next().css("color", (USERNAME==array[USER]) ? SOFT : BRIGHT ).append(": ") .parent() //      msg ; if (array[MSG]!=="") { //    msg.show(); // var div=msg.get(0); //    html- if (div) div.scrollIntoView(); //    } }; //drawMsg window.chat=function(array){ //  if ( $.isArray(array) ) drawMsg( array ); //  -   //     -  ? setTimeout( //     jQuery function(){ #call(..GetNext($(".msg:last span:first").text()))# } , #($get(^chatSettings("timeout"),300))# ); //    }; //window.chat chat(); //  - }); </script><body></body></html> <script runat="server" method="Add" arguments="msg:%String" language="cache"> #;    s ^chat($increment(^chat))=$listbuild( $zt( $now() ), $USERNAME, msg ) </script> <script runat="server" method="GetNext" arguments="lastMsg:%String" language="cache"> #;  c   set lastMsg=$get(lastMsg), prevMsg=$order( ^chat(lastMsg),-1 ), isNewUser=( lastMsg = "" ) set callBack="window.parent.chat(" ; set isNewChat=( isNewUser && (prevMsg="") ) if ( isNewChat ) write callBack,")" Quit if ( isNewUser ) write callBack,"[", prevMsg, ",'','',''])" Quit ; set nextMsg=$order( ^chat( lastMsg ) ) if ( nextMsg="" ) write callBack,")" Quit set stored=$get(^chat(nextMsg)) ;  write callBack,"[",nextMsg,", ", ..QuoteJS( $listget(stored,1) ) , ",", ..QuoteJS( $listget(stored,2) ) , ",", ..QuoteJS( ..EscapeHTML( $listget(stored,3 ))) , "])" </script> 

To play an example, open Studio in any area, create a new CSP page, paste the copied page code from the example. Save the page with any name - select any existing CSP application. Then compile the page (Ctrl + F7) and open it in the browser (F5).

Using jQuery on a Zen page

Using jQuery on a Zen page is completely similar to using CSP (searching and changing elements), but considering that Zen is a client-server framework that supports the same object model in the browser and on the Cache server. Therefore it is necessary to consider the following points:
- A Zen page model begins to form after a page load event.
- To change the page model, it is preferable to use Zen methods
- Zen forms markup with additional hidden elements

A practical example of Cache + jQuery
Let's take a more complex example using jQuery to create and delete objects of a stored class with the following interface:
Features of the example:
- The example works on Cache version 2010 and higher.
- Dynamic binding of events is used, all javascript code is moved to a separate javascript file
- Part of the page content is generated directly in the browser.
- “Hyper” events and “dynamic” (generated on the fly) page method are not used.
- The server generates responses in various data formats, depending on the request arguments.
- Shows the output of the server object in XML format using% XML.Writer and parsing the server response in XML format on the client side using jQuery

1. Create a stored class with test data in the User pane.
///
Class test.data Extends (%Persistent, %Populate, %XML.Adaptor) {
///
Property code As %String;
///
Property name As %String;
/// "",
Method %OnNew(ByRef args as %String="") As %Status [ Private, ServerOnly = 1 ] {
s ..code=$g(args("code",1)), ..name=$g(args("name",1))
Quit $$$OK
}
}


2. Create test data in test.data by running a class method call from the Cache terminal.
USER>d ##class(test.data).Populate()

3. Create a class page:
/// Page for working with test.data class instances
 Class wui.testData Extends %CSP.Page { ///   Parameter CHARSET="utf-8"; ///     ClassMethod OnPage() As %Status { #;       #; 1.   #; 2.    #; 3.    #;       <var>oper</var> m args=%request.Data ;     if $d(args("oper")){ //   oper s oper=$g(args("oper",1)) //   Q:oper="add" ..Add(.args) //        Q:oper="del" ..Del(.args) //    } #;       &html<<html><head><title> test.data</title> <!--     CSS --> <style type="text/css"> table {border-collapse: collapse; border: 1px solid #777;} td, th {border: 1px solid #777;} td {padding: 2px;} th {font-weight: normal; color:#fff;background-color:#aaa;} </style> </head> <body> <table><caption>  test.data</caption> <thead><tr><th>ID</th><th>code</th><th>name</th><th><!----></th></tr></thead> <tbody>> #;       s sql="Select ID,code,name From test.data" s rs=##class(%SQL.Statement).%ExecDirect(.stm, sql) ;    Cache > 2009 ? while rs.%Next() { w !,"<tr id='",rs.ID,"'>" , "<th>",rs.ID,"</th>" ;   , "<td>",rs.code,"</td>" , "<td>",rs.name,"</td>" , "</tr>" } &html<</tbody></table> <!-- jQuery--> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <!—      --> <script src="wui.testData.js"></script> </body></html>> Quit $$$OK } ///          XML ClassMethod Add(ByRef args as %String="") as %Status{ #;     s obj=##class(test.data).%New(.args), sc=obj.%Save() #;         xml s wr=##class(%XML.Writer).%New() ;  xml d wr.RootElement("response") ; <response , wr.WriteAttribute("id",obj.%Id()) ; id='' #;    xml d wr.Object(obj) ; ><data><code>123</code><name>Name</name></data> if $$$ISERR(sc) { d wr.Element("error") ;<error> d wr.WriteChars($system.Status.GetOneErrorText(sc)) ;errorText d wr.EndElement() ;</error> } d wr.EndRootElement() ;</response> Q $$$OK } ///           ClassMethod Del(ByRef args as %String="") as %Status{ s id=$g(args("id",1)), sc=##class(test.data).%DeleteId(id) w $CASE(sc ,1: 1 , : $system.Status.GetOneErrorText(sc) ) Q $$$OK } } 

The following is the Javascript code that was rendered to the wui.testData.js file. The file must be located in the csp-application directory. For the USER area, the directory is in the [Cache installation directory] \ CSP \ USER \.

 $(function(){ // document.ready //       var footer=[ //      "<tfoot><tr>" ,"<th>*</th>" // " " ,"<th><input /></th>" // "" ,"<th><input /></th>" // "" ,"<th><button> + </button></th>" //    ,"</tr></tfoot>" ].join( "" ); //   (   ) //     $( footer ).appendTo( $( "table" ) ); //     //        $( "tfoot button" ).click( callAdd ); //     //  tr  tbody (   test.Data)    $("tbody tr").each( addDelBtn ); //   //        function addDelBtn (){ //       var $tr=$(this); //  (tr  tbody)  jQuery $( "<th><button class='bDel'></button></th>" ) //  .appendTo( $tr ) //        .children( ".bDel" ) //   c  bDel .html( "X" ) //   .attr( "title", " " ) //   .css( "color", "#f00" ) //     .click( callDel ) //       ; }; //        function callDel(){ //  -   var $btnDel=$( this ).hide(); //       var $row=$button.parents( "tr" ); //   tr var id=$row.attr( "id" ); //   //        //  $.ajax- http://api.jquery.com/jQuery.ajax/ $.ajax({ //ajax options url: window.location //   - wui.testData.cls ,data: "oper=del&id="+id //  ,dataType: "text" //    text ,success: function(txt){ //    if ( txt!="1" ) { //    $btnDel.show(); //    alert(txt); //  return; } $row.remove(); //    } }); //ajax() }; //      function callAdd(){ var values = [] //         , $inputs = $( "tfoot input" ) //   //     .each( function(){ values.push( //    $( this ).val() // input ) } //function ) //each ; //var //,    -  if ( values.join( "" ) == "" ){ alert( "    " ); return; }; //        var $addRow = $( "tfoot tr" ).hide(); //         // $.ajax- http://api.jquery.com/jQuery.ajax/ $.ajax( { //   url: window.location // - wui.testData.cls //,async: true //      , type: "POST" //   - POST  GET , data: { //       oper: "add" //  , code: values[0] //  , name: values[1] //  } , dataType: 'text' //    . //    , success: function( text ){ //  c    XML   // <response id='newid'> // <data><code>Code</code><name>Name</name></data> // <error>Error Text</error> // </response> //      jQuery var xml=$.parseXML(text) , $xml=$( xml ) //   jQuery , error=$xml .find("error") // node   .text() //   ; if ( error!=="" ){ //  alert(error); //  return; } //     var id=$xml.find("response").attr("id") , code=$xml.find("code").text() , name=$xml.find("name").text(); var tr=[ //     "<tr id='",id,"'>" , "<th>",id,"</th>" , "<td>",code,"</td>" , "<td>",name,"</td>" ,"</tr>" ].join( "" ); $( tr ) .appendTo( $("table tbody") ) //    //        .each( addDelBtn ) ; $inputs.val( "" ) //   .focus() //  ; } //success , error: function(err){ //     alert("Error: "+err); } // ,   success  error , complete: function(){ $addRow.show(); //    } } // ); //$.ajax }; //callAdd }); //document.ready 


Some results:

Source: https://habr.com/ru/post/141996/


All Articles