গুগল ফটোগ্রাফি পুরস্কার গ্যালারি

Ilmari Heikkinen

গুগল ফটোগ্রাফি পুরস্কার ওয়েবসাইট

আমরা সম্প্রতি Google ফটোগ্রাফি পুরস্কার সাইটে গ্যালারি বিভাগ চালু করেছি। গ্যালারি Google+ থেকে আনা ফটোগুলির একটি অসীম স্ক্রলিং তালিকা দেখায়৷ এটি একটি AppEngine অ্যাপ থেকে ফটোগুলির তালিকা পায় যা আমরা গ্যালারিতে ফটোগুলির তালিকা নিয়ন্ত্রণ করার জন্য ব্যবহার করি। এছাড়াও আমরা Google Code- এ একটি ওপেন সোর্স প্রজেক্ট হিসেবে গ্যালারি অ্যাপটি প্রকাশ করেছি।

গ্যালারী পাতা

গ্যালারির ব্যাকএন্ড হল একটি AppEngine অ্যাপ যেটি Google+ এপিআই ব্যবহার করে এটিতে থাকা Google ফটোগ্রাফি প্রাইজ হ্যাশট্যাগগুলির একটি (যেমন #megpp এবং #travelgpp) সহ পোস্টগুলি অনুসন্ধান করতে। অ্যাপটি তারপর সেই পোস্টগুলিকে তার অনিয়ন্ত্রিত ফটোগুলির তালিকায় যুক্ত করে। সপ্তাহে একবার, আমাদের বিষয়বস্তু দল অসংযত ফটো এবং পতাকাগুলির তালিকার মধ্য দিয়ে যায় যা আমাদের সামগ্রী নির্দেশিকা ভঙ্গ করে। মডারেট-বোতামে আঘাত করার পরে, ফ্ল্যাগ করা ছবিগুলি গ্যালারি পৃষ্ঠায় প্রদর্শিত ফটোগুলির তালিকায় যোগ করা হয়।

মডারেশন ব্যাকএন্ড

গ্যালারি ফ্রন্টএন্ড Google ক্লোজার লাইব্রেরি ব্যবহার করে তৈরি করা হয়েছে। গ্যালারি উইজেট নিজেই একটি বন্ধ উপাদান। সোর্স ফাইলের শীর্ষে আমরা ক্লোজারকে বলি যে এই ফাইলটি photographyPrize.Gallery নামে একটি উপাদান সরবরাহ করে এবং অ্যাপ দ্বারা ব্যবহৃত ক্লোজার লাইব্রেরির অংশগুলির প্রয়োজন হয়:

goog.provide('photographyPrize.Gallery');

goog.require('goog.debug.Logger');
goog.require('goog.dom');
goog.require('goog.dom.classes');
goog.require('goog.events');
goog.require('goog.net.Jsonp');
goog.require('goog.style');

গ্যালারি পৃষ্ঠাটিতে কিছুটা জাভাস্ক্রিপ্ট রয়েছে যা AppEngine অ্যাপ থেকে ফটোগুলির তালিকা পুনরুদ্ধার করতে JSONP ব্যবহার করে। JSONP হল একটি সাধারণ ক্রস-অরিজিন জাভাস্ক্রিপ্ট হ্যাক যা jsonpcallback("responseValue") এর মতো দেখতে একটি স্ক্রিপ্ট ইনজেক্ট করে। JSONP স্টাফ পরিচালনা করতে, আমরা ক্লোজার লাইব্রেরিতে goog.net.Jsonp উপাদান ব্যবহার করছি।

গ্যালারি স্ক্রিপ্ট ফটোগুলির তালিকার মধ্য দিয়ে যায় এবং তাদের গ্যালারি পৃষ্ঠায় দেখানোর জন্য HTML উপাদান তৈরি করে। উইন্ডো স্ক্রোল ইভেন্টে হুক আপ করে এবং যখন উইন্ডো স্ক্রল পৃষ্ঠার নীচের দিকে থাকে তখন ফটোগুলির একটি নতুন ব্যাচ লোড করার মাধ্যমে অসীম স্ক্রলিং কাজ করে। নতুন ফটো তালিকা সেগমেন্ট লোড করার পরে, গ্যালারী স্ক্রিপ্ট ফটোগুলির জন্য উপাদান তৈরি করে এবং সেগুলিকে প্রদর্শন করার জন্য গ্যালারী উপাদানগুলিতে যুক্ত করে৷

ছবির তালিকা প্রদর্শন করা হচ্ছে

ইমেজ তালিকা প্রদর্শন পদ্ধতি বেশ মৌলিক উপাদান. এটি চিত্র তালিকার মধ্য দিয়ে যায়, HTML উপাদান এবং +1 বোতাম তৈরি করে। পরবর্তী ধাপ হল গ্যালারির প্রধান গ্যালারী উপাদানে জেনারেট করা তালিকার অংশ যোগ করা। আপনি নীচের কোডে কিছু ক্লোজার কম্পাইলার কনভেনশন দেখতে পারেন, JSDoc মন্তব্যে টাইপ সংজ্ঞা এবং @private দৃশ্যমানতা নোট করুন। ব্যক্তিগত পদ্ধতিতে তাদের নামের পরে একটি আন্ডারস্কোর (_) থাকে।

/**
 * Displays images in imageList by putting them inside the section element.
 * Edits image urls to scale them down to imageSize x imageSize bounding
 * box.
 *
 * @param {Array.<Object>} imageList List of image objects to show. Retrieved
 *                                   by loadImages.
 * @return {Element} The generated image list container element.
 * @private
 */
photographyPrize.Gallery.prototype.displayImages_ = function(imageList) {
  
  // find the images and albums from the image list
  for (var j = 0; j < imageList.length; j++) {
    // change image urls to scale them to photographyPrize.Gallery.MAX_IMAGE_SIZE
  }

  // Go through the image list and create a gallery photo element for each image.
  // This uses the Closure library DOM helper, goog.dom.createDom:
  // element = goog.dom.createDom(tagName, className, var_childNodes);

  var category = goog.dom.createDom('div', 'category');
  for (var k = 0; k < items.length; k++) {
    var plusone = goog.dom.createDom('g:plusone');
    plusone.setAttribute('href', photoPageUrl);
    plusone.setAttribute('size', 'standard');
    plusone.setAttribute('annotation', 'none');

    var photo = goog.dom.createDom('div', {className: 'gallery-photo'}, ...)
    photo.appendChild(plusone);

    category.appendChild(photo);
  }
  this.galleryElement_.appendChild(category);
  return category;
};

স্ক্রোল ইভেন্ট পরিচালনা করা

ভিজিটর কখন পৃষ্ঠাটি নীচে স্ক্রোল করেছে তা দেখতে এবং আমাদের নতুন ছবি লোড করতে হবে, গ্যালারিটি উইন্ডো অবজেক্টের স্ক্রোল ইভেন্টের সাথে হুক করে। ব্রাউজার ইমপ্লিমেন্টেশনের পার্থক্যের উপর কাগজপত্রের জন্য, আমরা ক্লোজার লাইব্রেরি থেকে কিছু সুবিধাজনক ইউটিলিটি ফাংশন ব্যবহার করছি: goog.dom.getDocumentScroll() বর্তমান নথির স্ক্রোল অবস্থানের সাথে একটি {x, y} অবজেক্ট প্রদান করে, goog.dom.getViewportSize() উইন্ডোর আকার এবং goog.dom.getDocumentHeight() HTML নথির উচ্চতা প্রদান করে।

/**
 * Handle window scroll events by loading new images when the scroll reaches
 * the last screenful of the page.
 *
 * @param {goog.events.BrowserEvent} ev The scroll event.
 * @private
 */
photographyPrize.Gallery.prototype.handleScroll_ = function(ev) {
  var scrollY = goog.dom.getDocumentScroll().y;
  var height = goog.dom.getViewportSize().height;
  var documentHeight = goog.dom.getDocumentHeight();
  if (scrollY + height >= documentHeight - height / 2) {
    this.tryLoadingNextImages_();
  }
};

/**
 * Try loading the next batch of images objects from the server.
 * Only fires if we have already loaded the previous batch.
 *
 * @private
 */
photographyPrize.Gallery.prototype.tryLoadingNextImages_ = function() {
  // ...
};

ছবি লোড হচ্ছে

সার্ভার থেকে ছবি লোড করতে, আমরা goog.net.Jsonp উপাদান ব্যবহার করছি। অনুসন্ধান করতে একটি goog.Uri লাগে৷ একবার তৈরি হয়ে গেলে, আপনি একটি ক্যোয়ারী প্যারামিটার অবজেক্ট এবং একটি সফল কলব্যাক ফাংশন সহ Jsonp প্রদানকারীর কাছে একটি প্রশ্ন পাঠাতে পারেন।

/**
 * Loads image list from the App Engine page and sets the callback function
 * for the image list load completion.
 *
 * @param {string} tag Fetch images tagged with this.
 * @param {number} limit How many images to fetch.
 * @param {number} offset Offset for the image list.
 * @param {function(Array.<Object>=)} callback Function to call
 *        with the loaded image list.
 * @private
 */
photographyPrize.Gallery.prototype.loadImages_ = function(tag, limit, offset, callback) {
  var jsonp = new goog.net.Jsonp(
      new goog.Uri(photographyPrize.Gallery.IMAGE_LIST_URL));
  jsonp.send({'tag': tag, 'limit': limit, 'offset': offset}, callback);
};

উপরে উল্লিখিত হিসাবে, গ্যালারি স্ক্রিপ্ট কোড সংকলন এবং ছোট করার জন্য ক্লোজার কম্পাইলার ব্যবহার করে। ক্লোজার কম্পাইলারটি সঠিক টাইপিং কার্যকর করার ক্ষেত্রেও কার্যকর (আপনি আপনার মন্তব্যে @type foo JSDoc স্বরলিপি ব্যবহার করেন একটি সম্পত্তির ধরন সেট করতে) এবং এটি আপনাকে বলে যে যখন আপনার কাছে কোনও পদ্ধতির জন্য মন্তব্য নেই।

ইউনিট পরীক্ষা

গ্যালারি স্ক্রিপ্টের জন্য আমাদের ইউনিট পরীক্ষারও প্রয়োজন ছিল, তাই এটি সহজ যে ক্লোজার লাইব্রেরিতে একটি ইউনিট টেস্টিং ফ্রেমওয়ার্ক তৈরি করা হয়েছে। এটি jsUnit নিয়মাবলী অনুসরণ করে, তাই এটি দিয়ে শুরু করা সহজ।

ইউনিট পরীক্ষা লিখতে আমাকে সাহায্য করার জন্য, আমি একটি ছোট রুবি স্ক্রিপ্ট লিখেছিলাম যা জাভাস্ক্রিপ্ট ফাইল পার্স করে এবং গ্যালারী উপাদানের প্রতিটি পদ্ধতি এবং সম্পত্তির জন্য একটি ব্যর্থ ইউনিট পরীক্ষা তৈরি করে। একটি স্ক্রিপ্ট দেওয়া যেমন:

Foo = function() {}
Foo.prototype.bar = function() {}
Foo.prototype.baz = "hello";

পরীক্ষা জেনারেটর প্রতিটি বৈশিষ্ট্যের জন্য একটি খালি পরীক্ষা তৈরি করে:

function testFoo() {
  fail();
  Foo();
}

function testFooPrototypeBar = function() {
  fail();
  instanceFoo.bar();
}

function testFooPrototypeBaz = function() {
  fail();
  instanceFoo.baz;
}

এই স্বয়ংক্রিয় পরীক্ষাগুলি আমাকে কোডের জন্য পরীক্ষা লেখার একটি সহজ সূচনা দিয়েছে এবং সমস্ত পদ্ধতি এবং বৈশিষ্ট্যগুলি ডিফল্টরূপে কভার করা হয়েছিল। ব্যর্থ পরীক্ষাগুলি একটি চমৎকার মনস্তাত্ত্বিক প্রভাব তৈরি করে যেখানে আমাকে একের পর এক পরীক্ষার মধ্য দিয়ে যেতে হয়েছিল এবং সঠিক পরীক্ষা লিখতে হয়েছিল। একটি কোড কভারেজ মিটারের সাথে মিলিত, এটি পরীক্ষা এবং কভারেজকে সবুজ করার জন্য একটি মজার খেলা।

সারসংক্ষেপ

গ্যালারি+ হল একটি ওপেন সোর্স প্রজেক্ট যা একটি #হ্যাশট্যাগের সাথে মিলে যাওয়া Google+ ফটোগুলির একটি সংযত তালিকা প্রদর্শন করে৷ এটি গো এবং ক্লোজার লাইব্রেরি ব্যবহার করে নির্মিত হয়েছিল। ব্যাকএন্ড অ্যাপ ইঞ্জিনে চলে। জমা গ্যালারি প্রদর্শন করতে Google ফটোগ্রাফি পুরস্কার ওয়েবসাইটে গ্যালারি+ ব্যবহার করা হয়। এই নিবন্ধে আমরা ফ্রন্টএন্ড স্ক্রিপ্টের সরস বিটগুলির মধ্য দিয়ে হেঁটেছি। অ্যাপ ইঞ্জিন ডেভেলপার রিলেশনস টিমের আমার সহকর্মী জোহান ইউফ্রোসাইন ব্যাকএন্ড অ্যাপ সম্পর্কে কথা বলে একটি দ্বিতীয় নিবন্ধ লিখছেন। ব্যাকএন্ডটি Go-তে লেখা হয়েছে, গুগলের নতুন সার্ভার-সাইড ভাষা। সুতরাং আপনি যদি গো কোডের একটি উৎপাদন উদাহরণ দেখতে আগ্রহী হন, তাহলে সাথে থাকুন!

তথ্যসূত্র