Home » Archives for 2016
Rabu, 21 Desember 2016
Minggu, 11 Desember 2016
[JavaScript] Looping with Delay
12/11/2016 Dida Nurwanda

Rabu, 09 November 2016
[CodeIgniter] Membuat Fitur Chat Pada Website Dengan Menggunakan CodeIgniter dan jQuery
11/09/2016 Dida Nurwanda

CREATE TABLE IF NOT EXISTS `chat` ( `chat_id` int(11) NOT NULL AUTO_INCREMENT, `send_to` int(5) NOT NULL, `send_by` int(3) NOT NULL, `message` tinytext NOT NULL, `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`chat_id`), KEY `sent_to` (`send_to`), KEY `send_by` (`send_by`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ; CREATE TABLE IF NOT EXISTS `users` ( `id` int(4) NOT NULL AUTO_INCREMENT, `name` varchar(200) NOT NULL, `username` varchar(32) NOT NULL, `password` varchar(64) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; INSERT INTO `users` (`id`, `name`, `username`, `password`) VALUES (1, 'Dida Nurwanda', 'didanurwanda', '$2y$10$1bxIR4tiYdycEvK6tLyUf.FUyP0EvWqeV/wzffKffnhe0R7e8Bqpe'), (2, 'Mark', 'mark', '$2y$10$gm8znIyAw3OyDsGFdsPIueRy2X0TmQmfiw5IFnJqyc55Eqd21hSWS'), (3, 'Ahmad Saepudin', 'ahmadesae', '$2y$10$dfnDoZCGQhT4unXGzWpCI.V8SbBPhJw3hjm4HcCFx53g4WE5nkC4G'); ALTER TABLE `chat` ADD CONSTRAINT `chat_ibfk_1` FOREIGN KEY (`send_by`) REFERENCES `users` (`id`);
Selanjutnya silahkan teman-teman persiapkan Framework CodeIgniter dan koneksikan dengan database yang telah teman-teman buat. Saya anggap ini sudah, selanjutnya buka Welcome.php pada folder controllers dan ubah isinya menjadi seperti berikut.
<?php
defined('BASEPATH') OR exit('No direct script access allowed'); class Welcome extends CI_Controller { public function __construct() { parent::__construct(); $this->load->library('session'); $this->load->database(); $this->load->helper(array('url', 'form')); } public function index() { if (isset($_POST['username'])) { $username = $this->input->post('username', true); $password = $this->input->post('password', true); if ($username !== '' && $password !== '') { $db = $this->db->get_where('users', array('username' => $username), 1)->row(); if ($db !== null && $db !== false && password_verify($password, $db->password)) { $newdata = array( 'user_id' => $db->id, 'username' => $username, 'logged_in' => TRUE ); $this->session->set_userdata($newdata); redirect('chat', 'refresh'); } } } $this->load->view('login'); } public function logout() { $this->session->sess_destroy(); redirect('welcome'); } }
<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?><!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Welcome to CodeIgniter</title> <link rel="stylesheet" type="text/css" href="<?= base_url('assets/styles.css') ?>"> </head> <body> <div id="container"> <h1>Welcome to CodeIgniter!</h1> <div id="body"> <?= form_open() ?> <div><label>Username</label></div> <div><?= form_input(array('name' => 'username', 'placeholder' => 'Username')) ?></div> <div><label>Password</label></div> <div><?= form_password(array('name' => 'password', 'placeholder' => 'Password', 'autocomplete' => 'new-password')) ?></div> <div><?= form_submit(array('value' => 'Login')) ?></div> <?= form_close() ?> <hr /> Demo (Username/Password) <hr /> didanurwanda/didanurwanda <br />mark/mark <br />ahmadsae/ahmadsae </div> <p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo (ENVIRONMENT === 'development') ? 'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p> </div> </body> </html>Sebelum berlanjut pada tujuan awal (Chat), teman-teman siapkan file jquery dan styles.css simpan di folder assets pada root directory, isi style seperti berikut
::selection { background-color: #E13300; color: white; } ::-moz-selection { background-color: #E13300; color: white; } body { background-color: #fff; margin: 40px; font: 13px/20px normal Helvetica, Arial, sans-serif; color: #4F5155; } a { color: #003399; background-color: transparent; font-weight: normal; } h1 { color: #444; background-color: transparent; border-bottom: 1px solid #D0D0D0; font-size: 19px; font-weight: normal; margin: 0 0 14px 0; padding: 14px 15px 10px 15px; } code { font-family: Consolas, Monaco, Courier New, Courier, monospace; font-size: 12px; background-color: #f9f9f9; border: 1px solid #D0D0D0; color: #002166; display: block; margin: 14px 0 14px 0; padding: 12px 10px 12px 10px; } #body { margin: 0 15px 0 15px; } p.footer { text-align: right; font-size: 11px; border-top: 1px solid #D0D0D0; line-height: 32px; padding: 0 10px 0 10px; margin: 20px 0 0 0; } #container { margin: 10px; border: 1px solid #D0D0D0; box-shadow: 0 0 8px #D0D0D0; } #table-friend tr { height: 30px; background: #cddbde; } #table-friend tr a { text-decoration: none; padding-left: 20px; color: #444; } /* message box header styles*/ .msg-wgt-container { position: fixed; bottom: 0; right: 20px; width: 250px; height: 300px; border: 1px solid #888888; } .minimize.msg-wgt-container { height: 29px; } .msg-wgt-header { width: 100%; height: 30px; line-height: 2.5em; text-align: center; background: #6f85b5 } .msg-wgt-header a { color: #ffffff; text-decoration: none; } .msg-wgt-header a.online { width: 10px; height: 10px; background: #66d266; position: absolute; left: 10px; top: 10px; border-radius: 10px; } .msg-wgt-header a.close { position: absolute; right: 10px; opacity: .7 } .msg-wgt-message-container { width: 100%; height: 230px; overflow-y: scroll; } .msg-wgt-message-list { width: 100%; } tr.msg-wgt-message-list-header { color: #999; font-size: 9px; vertical-align: top; } tr.msg-wgt-message-list-header img { width: 42px; } tr.msg-wgt-message-list-header .name { text-align: left; } tr.msg-wgt-message-list-header .time { text-align: right; } tr.msg-wgt-message-list-body td { font-size: 11px; color: #777; } tr.msg-wgt-message-list-separator td { border-bottom: 1px solid #ddd; } .msg-wgt-message-form { width: 100%; height: 40px; border-top: 1px solid #ddd; } .msg-wgt-message-form textarea { width: 98%; border: 0; height: 40px; }
Pada file css diatas, sudah berisi dari style untuk widget chat. Selanjutnya buat buat controller baru dengan nama Chat.php dan isi seperti berikut.
<?php class Chat extends CI_Controller { public $user; public function __construct() { parent::__construct(); $this->load->library('session'); $this->load->database(); $this->load->helper(array('url', 'form')); $this->load->library('user_agent'); if (!isset($this->session->userdata['logged_in']) || $this->session->userdata['logged_in'] === false) { redirect('welcome'); } $this->user = $this->db->get_where('users', array('id' => $this->session->userdata['user_id']), 1)->row(); } public function index() { $teman = $this->db->where('id !=', $this->user->id)->get('users'); $this->load->view('chat_dashboard', array( 'teman' => $teman )); } public function getChats() { header('Content-Type: application/json'); if ($this->input->is_ajax_request()) { // Find friend $friend = $this->db->get_where('users', array('id' => $this->input->post('chatWith')), 1)->row(); // Get Chats $chats = $this->db ->select('chat.*, users.name') ->from('chat') ->join('users', 'chat.send_by = users.id') ->where('(send_by = '. $this->user->id .' AND send_to = '. $friend->id .')') ->or_where('(send_to = '. $this->user->id .' AND send_by = '. $friend->id .')') ->order_by('chat.time', 'desc') // updated ->limit(100) // updated ->get() ->result(); $result = array( 'name' => $friend->name, 'chats' => $chats ); echo json_encode($result); } } public function sendMessage() { $this->db->insert('chat', array( 'message' => htmlentities($this->input->post('message', true)), 'send_to' => $this->input->post('chatWith'), 'send_by' => $this->user->id )); } }
Pada controller Chat inilah kita bisa mengirim dan menerima pesan, selanjutnya buat view dengan nama chat_dashboard.php
<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?><!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Chat Dashboard</title> <link rel="stylesheet" type="text/css" href="<?= base_url('assets/styles.css') ?>"> <script type="text/javascript" src="<?= base_url('assets/jquery.min.js') ?>"></script> </head> <body> <div id="container"> <h1> Selamat datang <?= $this->user->name ?>! <span style="float: right">Browser: <?= $this->agent->browser().' '.$this->agent->version() ?></span> </h1> <div id="body"> <p>Silahkan pilih teman:</p> <table style="width: 100%" id="table-friend"> <?php foreach ($teman->result() as $item) { ?> <tr> <td><a href="javascript:;" data-friend="<?= $item->id ?>"><?= $item->name ?></a></td> </tr> <?php } ?> </table> <br /> <br /> <a href="<?= site_url('welcome/logout') ?>">Logout</a> </div> </div> <!-- TEMPLATE --> <div id="wgt-container-template" style="display: none"> <div class="msg-wgt-container"> <div class="msg-wgt-header"> <a href="javascript:;" class="online"></a> <a href="javascript:;" class="name"></a> <a href="javascript:;" class="close">x</a> </div> <div class="msg-wgt-message-container"> <table width="100%" class="msg-wgt-message-list"> </table> </div> <div class="msg-wgt-message-form"> <textarea name="message" placeholder="Type your message. Press Shift + Enter for newline"></textarea> </div> </div> </div> <script type="text/x-template" id="msg-template" style="display: none"> <tbody> <tr class="msg-wgt-message-list-header"> <td rowspan="2"><img src="<?= base_url('assets/avatar.png') ?>"></td> <td class="name"></td> <td class="time"></td> </tr> <tr class="msg-wgt-message-list-body"> <td colspan="2"></td> </tr> <tr class="msg-wgt-message-list-separator"><td colspan="3"></td></tr> </tbody> </script> <script type="text/javascript"> jQuery(document).ready(function($) { var chatPosition = [ false, // 1 false, // 2 false, // 3 false, // 4 false, // 5 false, // 6 false, // 7 false, // 8 false, // 9 false // 10 ]; // New chat $(document).on('click', 'a[data-friend]', function(e) { var $data = $(this).data(); if ($data.friend !== undefined && chatPosition.indexOf($data.friend) < 0) { var posRight = 0; var position; for(var i in chatPosition) { if (chatPosition[i] == false) { posRight = (i * 270) + 20; chatPosition[i] = $data.friend; position = i; break; } } var tpl = $('#wgt-container-template').html(); var tplBody = $('<div/>').append(tpl); tplBody.find('.msg-wgt-container').addClass('msg-wgt-active'); tplBody.find('.msg-wgt-container').css('right', posRight + 'px'); tplBody.find('.msg-wgt-container').attr('data-chat-position', position); tplBody.find('.msg-wgt-container').attr('data-chat-with', $data.friend); $('body').append(tplBody.html()); initializeChat(); } }); // Minimize Maximize $(document).on('click', '.msg-wgt-header > a.name', function() { var parent = $(this).parent().parent(); if (parent.hasClass('minimize')) { parent.removeClass('minimize') } else { parent.addClass('minimize'); } }); // Close $(document).on('click', '.msg-wgt-header > a.close', function() { var parent = $(this).parent().parent(); var $data = parent.data(); parent.remove(); chatPosition[$data.chatPosition] = false; setTimeout(function() { initializeChat(); }, 1000) }); var chatInterval = []; var initializeChat = function() { $.each(chatInterval, function(index, val) { clearInterval(chatInterval[index]); }); $('.msg-wgt-active').each(function(index, el) { var $data = $(this).data(); var $that = $(this); var $container = $that.find('.msg-wgt-message-container'); chatInterval.push(setInterval(function() { var oldscrollHeight = $container[0].scrollHeight; var oldLength = 0; $.post('<?= site_url('chat/getChats') ?>', {chatWith: $data.chatWith}, function(data, textStatus, xhr) { $that.find('a.name').text(data.name); // from last var chatLength = data.chats.length; var newIndex = data.chats.length; $.each(data.chats, function(index, el) { newIndex--; var val = data.chats[newIndex]; var tpl = $('#msg-template').html(); var tplBody = $('<div/>').append(tpl); var id = (val.chat_id +'_'+ val.send_by +'_'+ val.send_to).toString(); if ($that.find('#'+ id).length == 0) { tplBody.find('tbody').attr('id', id); // set id tplBody.find('td.name').text(val.name); // set name tplBody.find('td.time').text(val.time); // set time tplBody.find('.msg-wgt-message-list-body > td').html(nl2br(val.message)); // set message $that.find('.msg-wgt-message-list').append(tplBody.html()); // append message //Auto-scroll var newscrollHeight = $container[0].scrollHeight - 20; //Scroll height after the request if (newIndex === 0) { $container.animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div } } }); }); }, 1000)); $that.find('textarea').on('keydown', function(e) { var $textArea = $(this); if (e.keyCode === 13 && e.shiftKey === false) { $.post('<?= site_url('chat/sendMessage') ?>', {message: $textArea.val(), chatWith: $data.chatWith}, function(data, textStatus, xhr) { }); $textArea.val(''); // clear input e.preventDefault(); // stop return false; } }); }); } var nl2br = function(str, is_xhtml) { // PHP JS var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br ' + '/>' : '<br>'; // Adjust comment to avoid issue on phpjs.org display return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); } // on load initializeChat(); }); </script> </body> </html>
Pembuatan file selesai dan saya tidak menggunakan model pada contoh kali ini karena isinya sangat sederhana. Sedikit penjelasan, pada chat ini saya membuat 2 template untuk widget dan untuk isi chat, teman-teman dapat melihatnya pada chat_dashboard, dengan template ini kita bisa menambahkan widget dengan cepat tanpa harus membuat manual dengan javascript. Widget ini juga saya batasi hanya dapat menampung 10 chat saja. Tidak banyak memang, teman-teman bisa menambahkannya sesuka hati kok. Berikut adalah tampilannya
Rabu, 03 Februari 2016
[CodeIgniter] Contoh CRUD W2-desktop dengan CodeIgniter
2/03/2016 Dida Nurwanda
Grid ini telah terintegrasi dengan Infinite Scroll
Untuk Yii Framework 2 akan menyusul beberapa hari kedepan.
Kamis, 07 Januari 2016
[Yii Framework 2] Integrasi Wysiwyg CKEditor dengan ElFinder pada Yii Framework 2
1/07/2016 Dida Nurwanda
Penggunaan Wysiwyg Editor pada website memang sangat penting, telebih jika website tersebut mengandung informasi/berita yang berisi tulisan dinamis dan rapi. Salah satu Wysiwyg yang terkenal dan banyak digunakan adalah CKEditor. Namun pada CKEditor tidak terintegrasi fitur untuk upload gambar, namun bisa Anda tambahkan fitur tersebut dengan beberapa plugin. Pada kesempatan ini saya membuat sedikit contoh integrasi CKEditor dengan ElFinder khusus untuk pengguna Yii Framework 2.
Sebagai catatan, pada tutorial ini menggunakan fasilitasi yang disediakan oleh Composer. Jika Anda belum memahami Composer, silahkan Anda pelajari terlebih dahulu.
Langsung saja, kali ini saya membuat contoh menggunakan template BASIC. Kemudian buat database dengan nama apa saja, namun disini saya membuat database dengan nama 'yii_ckeditor_elfinder' kemudian diisi dengaan table seperti berikut :
CREATE TABLE IF NOT EXISTS `artikel` ( `id` int(3) NOT NULL AUTO_INCREMENT, `judul` varchar(200) NOT NULL, `isi_artikel` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Oya pastikan Anda telah menginstall Yii Framework 2 pada workspace anda. kemudian atur database dengan yang telah Anda buat. Kemudanan generate Model dan CRUD. Jika telah selesai kemudaian instal widget berikut pada composer.
composer require --prefer-dist mihaildev/yii2-elfinder "*" composer require --prefer-dist mihaildev/yii2-ckeditor "*"Jika semua telah dilakukan, Sekarang anda buat folder dengan nama files pada directory "/projectyii/web/files" setelah itu buka file /config/web.php dan tambahkan beberapa baris kode seperti berikut.
$config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'controllerMap' => [ 'imagebrowser' => [ 'class' => 'mihaildev\elfinder\PathController', 'access' => ['@'], 'root' => [ 'path' => 'files', 'name' => 'Files' ], 'watermark' => [ 'source' => __DIR__.'/logo.png', // Path to Water mark image 'marginRight' => 5, // Margin right pixel 'marginBottom' => 5, // Margin bottom pixel 'quality' => 95, // JPEG image save quality 'transparency' => 70, // Water mark image transparency ( other than PNG ) 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field ) 'targetMinPixel' => 200 // Target image minimum pixel size ] ] ], 'components' => [ ... ] ];
public function behaviors() { return [ 'access' => [ 'class' => \yii\filters\AccessControl::className(), 'only' => ['create', 'delete', 'update'], 'rules' => [ [ 'allow' => true, 'roles' => ['@'], ], ], ],
Kemudian kita ubah form artikel agar tampil CKEditornya. Ubah seperti berikut.
<?php use yii\helpers\Html; use yii\widgets\ActiveForm; use mihaildev\ckeditor\CKEditor; use mihaildev\elfinder\ElFinder; /* @var $this yii\web\View */ /* @var $model app\models\Artikel */ /* @var $form yii\widgets\ActiveForm */ ?> <div class="artikel-form"> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'judul')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'isi_artikel')->widget(CKEditor::className(), [ 'editorOptions' => ElFinder::ckeditorOptions('imagebrowser',[/* Some CKEditor Options */]), ]) ?> <div class="form-group"> <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> </div> <?php ActiveForm::end(); ?> </div>
Agar hasilnya terlihat, kemudian ubah file view.php pada folder artikel seperti berikut
<?php use yii\helpers\Html; use yii\widgets\DetailView; /* @var $this yii\web\View */ /* @var $model app\models\Artikel */ $this->title = $model->id; $this->params['breadcrumbs'][] = ['label' => 'Artikels', 'url' => ['index']]; $this->params['breadcrumbs'][] = $this->title; ?> <div class="artikel-view"> <h1><?= Html::encode($model->judul) ?></h1> <hr /> <?= $model->isi_artikel ?> </div>
Selesai, jika berhasil, maka hasilnya seperti berikut